diff options
80 files changed, 4134 insertions, 958 deletions
diff --git a/include/assert.h b/include/assert.h index a3dbe933e18f..75d3e62e8932 100644 --- a/include/assert.h +++ b/include/assert.h @@ -46,23 +46,50 @@ #undef __assert_unreachable #ifdef NDEBUG -#define assert(e) ((void)0) -#define _assert(e) ((void)0) +#define assert(...) ((void)0) +#define _assert(...) ((void)0) #if __BSD_VISIBLE -#define __assert_unreachable() __unreachable() -#endif /* __BSD_VISIBLE */ +#define __assert_unreachable() __unreachable() +#endif /* __BSD_VISIBLE */ #else -#define _assert(e) assert(e) - -#define assert(e) ((e) ? (void)0 : __assert(__func__, __FILE__, \ - __LINE__, #e)) +#ifdef __cplusplus +#if __cplusplus < 202002L +/* + * C++ modes prior to C++20 cannot simultaneously satisfy all three + * desirable properties of the sanitiser: + * + * Approach No double-eval Lambda support Arity check + * ----------------------------- -------------- -------------- ----------- + * sizeof(cast(expression)) yes no yes + * static_cast<bool>(expression) no yes no + * (void)bool(expression) no yes no + * + * NOTE: C++20 introduced lambdas in unevaluated contexts; see P0315R4. + * + * Since no approach satisfies all three below C++20, the least harmful + * choice is to forgo the check entirely rather than silently break one + * of the remaining guarantees. + * + */ +#define __assert_sanitize(...) ((void)0) +#else +#define __assert_sanitize(...) (void)sizeof(((bool(*)(bool))0)(__VA_ARGS__)) +#endif /* __cplusplus < 202002L */ +#else +#define __assert_sanitize(...) (void)sizeof(((_Bool(*)(_Bool))0)(__VA_ARGS__)) +#endif /* __cplusplus */ +#define assert(...) (__assert_sanitize(__VA_ARGS__), \ + (__VA_ARGS__) ? (void)0 : \ + __assert(__func__, __FILE__, \ + __LINE__, #__VA_ARGS__)) +#define _assert(...) assert(__VA_ARGS__) #if __BSD_VISIBLE -#define __assert_unreachable() assert(0 && "unreachable segment reached") -#endif /* __BSD_VISIBLE */ +#define __assert_unreachable() assert(0 && "unreachable segment reached") +#endif /* __BSD_VISIBLE */ #endif /* NDEBUG */ -#ifndef _ASSERT_H_ -#define _ASSERT_H_ +#ifndef __STDC_VERSION_ASSERT_H__ +#define __STDC_VERSION_ASSERT_H__ 202311L /* * Static assertions. In principle we could define static_assert for @@ -72,13 +99,17 @@ * C++ template parameters may contain commas, even if not enclosed in * parentheses, causing the _Static_assert macro to be invoked with more * than two parameters. + * + * C23 defines static_assert and its obsolescent alternative spelling, + * _Static_assert, as keywords. */ -#if __ISO_C_VISIBLE >= 2011 && !defined(__cplusplus) -#define static_assert _Static_assert +#if __ISO_C_VISIBLE >= 2011 && !defined(__cplusplus) && \ + __STDC_VERSION__ < 202311L +#define static_assert _Static_assert #endif __BEGIN_DECLS void __assert(const char *, const char *, int, const char *) __dead2; __END_DECLS -#endif /* !_ASSERT_H_ */ +#endif /* !__STDC_VERSION_ASSERT_H__ */ diff --git a/include/rpcsvc/yp_prot.h b/include/rpcsvc/yp_prot.h index 091347231c8b..d0ad15bd657c 100644 --- a/include/rpcsvc/yp_prot.h +++ b/include/rpcsvc/yp_prot.h @@ -67,11 +67,6 @@ * YPPROC_MAPLIST takes (char *), returns (struct ypmaplist *). */ -#ifndef BOOL_DEFINED -typedef u_int bool; -#define BOOL_DEFINED -#endif - /* Program and version symbols, magic numbers */ #define YPPROG ((u_long)100004) diff --git a/lib/libc/gen/fts.3 b/lib/libc/gen/fts.3 index 199603b5f3c7..b6dbfffe8079 100644 --- a/lib/libc/gen/fts.3 +++ b/lib/libc/gen/fts.3 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd May 21, 2026 +.Dd May 29, 2026 .Dt FTS 3 .Os .Sh NAME @@ -497,6 +497,13 @@ field to and leave the contents of the .Fa statp field undefined. +The roots and any directories encountered during traversal +.Po +.Dv FTS_D , +.Dv FTS_DC , +.Dv FTS_DP +.Pc +are still fully populated. .It Dv FTS_NOSTAT_TYPE This option is similar to .Dv FTS_NOSTAT , diff --git a/lib/libc/gen/fts.c b/lib/libc/gen/fts.c index 4aa386d777cd..e8063ecb646e 100644 --- a/lib/libc/gen/fts.c +++ b/lib/libc/gen/fts.c @@ -41,6 +41,7 @@ #include <fcntl.h> #include <fts.h> #include <stdalign.h> +#include <stdint.h> #include <stdlib.h> #include <string.h> #include <unistd.h> @@ -114,6 +115,19 @@ static const char *ufslike_filesystems[] = { 0 }; +/* + * POSIX provides nlink_t but unfortunately not NLINK_MAX. + */ +#define NLINK_MAX \ + _Generic((nlink_t)0, \ + int16_t: INT16_MAX, \ + uint16_t: UINT16_MAX, \ + int32_t: INT32_MAX, \ + uint32_t: UINT32_MAX, \ + int64_t: INT64_MAX, \ + uint64_t: UINT64_MAX, \ + default: 0) + static FTS * __fts_open(FTS *sp, char * const *argv) { @@ -736,7 +750,7 @@ fts_build(FTS *sp, int type) int cderrno, descend, oflag, saved_errno, nostat, doadjust, readdir_errno; long level; - long nlinks; /* has to be signed because -1 is a magic value */ + int64_t nlinks; /* has to be signed because -1 is a magic value */ size_t dnamlen, len, maxlen, nitems; /* Set current node pointer. */ @@ -759,16 +773,36 @@ fts_build(FTS *sp, int type) } /* - * Nlinks is the number of possible entries of type directory in the - * directory if we're cheating on stat calls, 0 if we're not doing - * any stat calls at all, -1 if we're doing stats on everything. + * In the FTS_PHYSICAL | FTS_NOSTAT case, we want to avoid calling + * fstat() unnecessarily, but we still need to call it for + * subdirectories. The current directory's link count provides an + * upper bound on the number of subdirectories we may encounter + * (including . and .. in the FTS_SEEDOT case). We initialize + * nlinks to the current directory's link count, then decrement it + * every time we encounter a directory, so when we hit zero we can + * save some time by not calling fstat() on subsequent entries. + * + * If FTS_NOSTAT is not set, or the link count is less than two + * (which should not be possible) or equal to NLINK_MAX (which + * suggests that the actual value could be higher), or the current + * filesystem is not known to provide reliable link counts, we + * initialize nlinks to -1 and fstat() everything. + * + * In the rare case where we don't need to stat anything, even + * subdirectories, we initialize nlinks to 0 regardless of the + * actual link count. + * + * Note that we ignore the FTS_NOSTAT flag in the FTS_LOGICAL + * case, although we could choose to only stat symbolic links. + * Implementing this is left as an exercise for the reader. */ if (type == BNAMES) { nlinks = 0; /* Be quiet about nostat, GCC. */ nostat = 0; } else if (ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL)) { - if (fts_ufslinks(sp, cur)) + if (cur->fts_nlink >= 2 && cur->fts_nlink < NLINK_MAX && + cur->fts_nlink <= INT64_MAX && fts_ufslinks(sp, cur)) nlinks = cur->fts_nlink - (ISSET(FTS_SEEDOT) ? 0 : 2); else nlinks = -1; diff --git a/lib/libc/tests/gen/fts_options_test.c b/lib/libc/tests/gen/fts_options_test.c index fc3015138a49..863c0809d16e 100644 --- a/lib/libc/tests/gen/fts_options_test.c +++ b/lib/libc/tests/gen/fts_options_test.c @@ -36,6 +36,8 @@ fts_options_prepare(const struct atf_tc *tc) ATF_REQUIRE_EQ(0, mkdir("dir", 0755)); ATF_REQUIRE_EQ(0, close(creat("file", 0644))); ATF_REQUIRE_EQ(0, close(creat("dir/file", 0644))); + ATF_REQUIRE_EQ(0, mkdir("dir/sd", 0750)); + ATF_REQUIRE_EQ(0, mkdir("dir/sd/sd", 0700)); ATF_REQUIRE_EQ(0, symlink("..", "dir/up")); ATF_REQUIRE_EQ(0, symlink("dir", "dirl")); ATF_REQUIRE_EQ(0, symlink("file", "filel")); @@ -57,6 +59,10 @@ ATF_TC_BODY(fts_options_logical, tc) { FTS_DL, "dead", "dead" }, { FTS_D, "dir", "dir" }, { FTS_F, "file", "dir/file" }, + { FTS_D, "sd", "dir/sd" }, + { FTS_D, "sd", "dir/sd/sd" }, + { FTS_DP, "sd", "dir/sd/sd" }, + { FTS_DP, "sd", "dir/sd" }, { FTS_D, "up", "dir/up" }, { FTS_DL, "dead", "dir/up/dead" }, { FTS_DC, "dir", "dir/up/dir" }, @@ -67,6 +73,10 @@ ATF_TC_BODY(fts_options_logical, tc) { FTS_DP, "dir", "dir" }, { FTS_D, "dirl", "dirl" }, { FTS_F, "file", "dirl/file" }, + { FTS_D, "sd", "dirl/sd" }, + { FTS_D, "sd", "dirl/sd/sd" }, + { FTS_DP, "sd", "dirl/sd/sd" }, + { FTS_DP, "sd", "dirl/sd" }, { FTS_D, "up", "dirl/up" }, { FTS_DL, "dead", "dirl/up/dead" }, { FTS_DC, "dir", "dirl/up/dir" }, @@ -108,6 +118,10 @@ ATF_TC_BODY(fts_options_logical_nostat, tc) { FTS_DL, "dead", "dead" }, { FTS_D, "dir", "dir" }, { FTS_NSOK, "file", "dir/file" }, + { FTS_D, "sd", "dir/sd" }, + { FTS_D, "sd", "dir/sd/sd" }, + { FTS_DP, "sd", "dir/sd/sd" }, + { FTS_DP, "sd", "dir/sd" }, { FTS_D, "up", "dir/up" }, { FTS_DL, "dead", "dir/up/dead" }, { FTS_DC, "dir", "dir/up/dir" }, @@ -118,6 +132,10 @@ ATF_TC_BODY(fts_options_logical_nostat, tc) { FTS_DP, "dir", "dir" }, { FTS_D, "dirl", "dirl" }, { FTS_NSOK, "file", "dirl/file" }, + { FTS_D, "sd", "dirl/sd" }, + { FTS_D, "sd", "dirl/sd/sd" }, + { FTS_DP, "sd", "dirl/sd/sd" }, + { FTS_DP, "sd", "dirl/sd" }, { FTS_D, "up", "dirl/up" }, { FTS_DL, "dead", "dirl/up/dead" }, { FTS_DC, "dir", "dirl/up/dir" }, @@ -151,6 +169,14 @@ ATF_TC_BODY(fts_options_logical_seedot, tc) { FTS_DOT, ".", "dir/." }, { FTS_DOT, "..", "dir/.." }, { FTS_F, "file", "dir/file" }, + { FTS_D, "sd", "dir/sd" }, + { FTS_DOT, ".", "dir/sd/." }, + { FTS_DOT, "..", "dir/sd/.." }, + { FTS_D, "sd", "dir/sd/sd" }, + { FTS_DOT, ".", "dir/sd/sd/." }, + { FTS_DOT, "..", "dir/sd/sd/.." }, + { FTS_DP, "sd", "dir/sd/sd" }, + { FTS_DP, "sd", "dir/sd" }, { FTS_D, "up", "dir/up" }, { FTS_DOT, ".", "dir/up/." }, { FTS_DOT, "..", "dir/up/.." }, @@ -165,6 +191,14 @@ ATF_TC_BODY(fts_options_logical_seedot, tc) { FTS_DOT, ".", "dirl/." }, { FTS_DOT, "..", "dirl/.." }, { FTS_F, "file", "dirl/file" }, + { FTS_D, "sd", "dirl/sd" }, + { FTS_DOT, ".", "dirl/sd/." }, + { FTS_DOT, "..", "dirl/sd/.." }, + { FTS_D, "sd", "dirl/sd/sd" }, + { FTS_DOT, ".", "dirl/sd/sd/." }, + { FTS_DOT, "..", "dirl/sd/sd/.." }, + { FTS_DP, "sd", "dirl/sd/sd" }, + { FTS_DP, "sd", "dirl/sd" }, { FTS_D, "up", "dirl/up" }, { FTS_DOT, ".", "dirl/up/." }, { FTS_DOT, "..", "dirl/up/.." }, @@ -198,6 +232,10 @@ ATF_TC_BODY(fts_options_physical, tc) { FTS_SL, "dead", "dead" }, { FTS_D, "dir", "dir" }, { FTS_F, "file", "file" }, + { FTS_D, "sd", "sd" }, + { FTS_D, "sd", "sd" }, + { FTS_DP, "sd", "sd" }, + { FTS_DP, "sd", "sd" }, { FTS_SL, "up", "up" }, { FTS_DP, "dir", "dir" }, { FTS_SL, "dirl", "dirl" }, @@ -224,6 +262,10 @@ ATF_TC_BODY(fts_options_physical_nochdir, tc) { FTS_SL, "dead", "dead" }, { FTS_D, "dir", "dir" }, { FTS_F, "file", "dir/file" }, + { FTS_D, "sd", "dir/sd" }, + { FTS_D, "sd", "dir/sd/sd" }, + { FTS_DP, "sd", "dir/sd/sd" }, + { FTS_DP, "sd", "dir/sd" }, { FTS_SL, "up", "dir/up" }, { FTS_DP, "dir", "dir" }, { FTS_SL, "dirl", "dirl" }, @@ -250,10 +292,18 @@ ATF_TC_BODY(fts_options_physical_comfollow, tc) { FTS_DL, "dead", "dead" }, { FTS_D, "dir", "dir" }, { FTS_F, "file", "file" }, + { FTS_D, "sd", "sd" }, + { FTS_D, "sd", "sd" }, + { FTS_DP, "sd", "sd" }, + { FTS_DP, "sd", "sd" }, { FTS_SL, "up", "up" }, { FTS_DP, "dir", "dir" }, { FTS_D, "dirl", "dirl" }, { FTS_F, "file", "file" }, + { FTS_D, "sd", "sd" }, + { FTS_D, "sd", "sd" }, + { FTS_DP, "sd", "sd" }, + { FTS_DP, "sd", "sd" }, { FTS_SL, "up", "up" }, { FTS_DP, "dirl", "dirl" }, { FTS_F, "file", "file" }, @@ -279,10 +329,18 @@ ATF_TC_BODY(fts_options_physical_comfollowdir, tc) { FTS_DL, "dead", "dead" }, { FTS_D, "dir", "dir" }, { FTS_F, "file", "file" }, + { FTS_D, "sd", "sd" }, + { FTS_D, "sd", "sd" }, + { FTS_DP, "sd", "sd" }, + { FTS_DP, "sd", "sd" }, { FTS_SL, "up", "up" }, { FTS_DP, "dir", "dir" }, { FTS_D, "dirl", "dirl" }, { FTS_F, "file", "file" }, + { FTS_D, "sd", "sd" }, + { FTS_D, "sd", "sd" }, + { FTS_DP, "sd", "sd" }, + { FTS_DP, "sd", "sd" }, { FTS_SL, "up", "up" }, { FTS_DP, "dirl", "dirl" }, { FTS_F, "file", "file" }, @@ -308,6 +366,10 @@ ATF_TC_BODY(fts_options_physical_nostat, tc) { FTS_SL, "dead", "dead" }, { FTS_D, "dir", "dir" }, { FTS_NSOK, "file", "file" }, + { FTS_D, "sd", "sd" }, + { FTS_D, "sd", "sd" }, + { FTS_DP, "sd", "sd" }, + { FTS_DP, "sd", "sd" }, { FTS_NSOK, "up", "up" }, { FTS_DP, "dir", "dir" }, { FTS_SL, "dirl", "dirl" }, @@ -334,6 +396,10 @@ ATF_TC_BODY(fts_options_physical_nostat_type, tc) { FTS_SL, "dead", "dead" }, { FTS_D, "dir", "dir" }, { FTS_F, "file", "file" }, + { FTS_D, "sd", "sd" }, + { FTS_D, "sd", "sd" }, + { FTS_DP, "sd", "sd" }, + { FTS_DP, "sd", "sd" }, { FTS_SL, "up", "up" }, { FTS_DP, "dir", "dir" }, { FTS_SL, "dirl", "dirl" }, @@ -362,6 +428,14 @@ ATF_TC_BODY(fts_options_physical_seedot, tc) { FTS_DOT, ".", "." }, { FTS_DOT, "..", ".." }, { FTS_F, "file", "file" }, + { FTS_D, "sd", "sd" }, + { FTS_DOT, ".", "." }, + { FTS_DOT, "..", ".." }, + { FTS_D, "sd", "sd" }, + { FTS_DOT, ".", "." }, + { FTS_DOT, "..", ".." }, + { FTS_DP, "sd", "sd" }, + { FTS_DP, "sd", "sd" }, { FTS_SL, "up", "up" }, { FTS_DP, "dir", "dir" }, { FTS_SL, "dirl", "dirl" }, diff --git a/lib/libutil/login_class.c b/lib/libutil/login_class.c index 90e4e01f7c3b..8a465e2eb24e 100644 --- a/lib/libutil/login_class.c +++ b/lib/libutil/login_class.c @@ -63,9 +63,9 @@ static struct login_res { { "vmemoryuse", login_getcapsize, RLIMIT_VMEM }, { "pseudoterminals", login_getcapnum, RLIMIT_NPTS }, { "swapuse", login_getcapsize, RLIMIT_SWAP }, - { "kqueues", login_getcapsize, RLIMIT_KQUEUES }, + { "kqueues", login_getcapnum, RLIMIT_KQUEUES }, { "umtxp", login_getcapnum, RLIMIT_UMTXP }, - { "pipebuf", login_getcapnum, RLIMIT_PIPEBUF }, + { "pipebuf", login_getcapsize, RLIMIT_PIPEBUF }, { "vms", login_getcapnum, RLIMIT_VMM }, { NULL, 0, 0 } }; diff --git a/libexec/rc/rc.conf b/libexec/rc/rc.conf index 75420e42cdeb..27e8c8456b6f 100644 --- a/libexec/rc/rc.conf +++ b/libexec/rc/rc.conf @@ -736,7 +736,11 @@ newsyslog_flags="-CN" # Newsyslog flags to create marked files mixer_enable="YES" # Run the sound mixer. opensm_enable="NO" # Opensm(8) for infiniband devices defaults to off nuageinit_enable="NO" # Run nuageinit at startup -virtual_oss_enable="NO" # Run virtual_oss at startup + +virtual_oss_enable="NO" # Run virtual_oss at startup. +virtual_oss_configs="dsp" # List of configurations. +virtual_oss_default_control_device="vdsp.ctl" # Default configuration's + # control device. # rctl(8) requires kernel options RACCT and RCTL rctl_enable="YES" # Load rctl(8) rules on boot diff --git a/libexec/rc/rc.d/virtual_oss b/libexec/rc/rc.d/virtual_oss index 73a486f547a5..9861545b8bfc 100644 --- a/libexec/rc/rc.d/virtual_oss +++ b/libexec/rc/rc.d/virtual_oss @@ -22,13 +22,9 @@ status_cmd="${name}_status" required_modules="cuse" -configs= pidpath="/var/run/${name}" -default_unit=$(sysctl -n hw.snd.default_unit 2> /dev/null) - -# Default configuration's control device. -: "${virtual_oss_default_control_device:="vdsp.ctl"}" +default_unit=$(sysctl -n hw.snd.default_unit 2> /dev/null) virtual_oss_default_args="\ -S \ -C 2 \ @@ -42,12 +38,6 @@ virtual_oss_default_args="\ -l dsp.loop \ -t ${virtual_oss_default_control_device}" -# Set to NO by default. Set it to "YES" to enable virtual_oss. -: "${virtual_oss_enable:="NO"}" - -# List of configurations to use. Default is "dsp". -: "${virtual_oss_configs:="dsp"}" - # Default (dsp) virtual_oss config. : "${virtual_oss_dsp:="${virtual_oss_default_args}"}" @@ -86,10 +76,17 @@ stop_instance() if [ -z "${instance_args}" ]; then warn "no such config: ${config}" else - startmsg -n "Stopping virtual_oss config: ${config}: " - kill "$(cat "${pidpath}/${config}.pid")" - rm -f "${pidpath}/${config}.pid" - startmsg "done" + pidfile="${pidpath}/${config}.pid" + if [ ! -f "${pidfile}" ]; then + warn "not running: ${config}" + else + pid="$(cat "${pidfile}")" + startmsg -n "Stopping virtual_oss config: ${config}: " + kill "${pid}" + pwait "${pid}" + rm -f "${pidfile}" + startmsg "done" + fi fi } diff --git a/sbin/mdmfs/mdmfs.c b/sbin/mdmfs/mdmfs.c index cd0bf7c96143..c86a098a892d 100644 --- a/sbin/mdmfs/mdmfs.c +++ b/sbin/mdmfs/mdmfs.c @@ -49,14 +49,13 @@ #include <paths.h> #include <pwd.h> #include <stdarg.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <unistd.h> -typedef enum { false, true } bool; - struct mtpt_info { uid_t mi_uid; bool mi_have_uid; diff --git a/sbin/ping/tests/ping_test.sh b/sbin/ping/tests/ping_test.sh index af700615dc8d..ab45ad809a52 100644 --- a/sbin/ping/tests/ping_test.sh +++ b/sbin/ping/tests/ping_test.sh @@ -253,14 +253,22 @@ inject_reply_cleanup() ifconfig `cat tun.txt` destroy } -atf_test_case timestamp_origin +atf_test_case timestamp_origin cleanup timestamp_origin_head() { atf_set "descr" "ICMP Originate Timestamp" + atf_set "require.user" "root" + atf_set "require.config" "allow_sysctl_side_effects" } timestamp_origin_body() { require_ipv4 + # The kernel only replies to ICMP timestamp requests when + # net.inet.icmp.tstamprepl is enabled. Save the current value + # so the cleanup hook can restore it, then enable replies. + sysctl -n net.inet.icmp.tstamprepl > tstamprepl.txt + sysctl net.inet.icmp.tstamprepl=1 + # Run ping timestamp out=$(ping -Mt -c1 127.0.0.1) @@ -286,6 +294,12 @@ timestamp_origin_body() atf_fail "tso ($tso) differs from tsr ($tsr) by $diff seconds" fi } +timestamp_origin_cleanup() +{ + if [ -f tstamprepl.txt ]; then + sysctl net.inet.icmp.tstamprepl=`cat tstamprepl.txt` + fi +} atf_init_test_cases() { diff --git a/sbin/route/route_netlink.c b/sbin/route/route_netlink.c index 051662688047..0d4420767082 100644 --- a/sbin/route/route_netlink.c +++ b/sbin/route/route_netlink.c @@ -950,7 +950,8 @@ flushroutes_fib_nl(int fib, int af) struct snl_msg_info attrs = {}; print_nlmsg(&h, hdr, &attrs); } - if (r.rta_table != (uint32_t)fib || r.rtm_family != af) + if (r.rta_table != (uint32_t)fib || + (af != AF_UNSPEC && r.rtm_family != af)) continue; if ((r.rta_rtflags & RTF_GATEWAY) == 0) continue; diff --git a/share/man/man3/assert.3 b/share/man/man3/assert.3 index f219aa1d6743..2782ffe7de18 100644 --- a/share/man/man3/assert.3 +++ b/share/man/man3/assert.3 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd April 20, 2021 +.Dd May 17, 2026 .Dt ASSERT 3 .Os .Sh NAME @@ -40,15 +40,14 @@ .Sh DESCRIPTION The .Fn assert -macro tests the given -.Ar expression +macro tests the given scalar +.Ar expression , and if it is false, -the calling process is terminated. -A diagnostic message is written to +a diagnostic message is written to .Dv stderr and the function .Xr abort 3 -is called, effectively terminating the program. +is called, effectively terminating the calling process. .Pp If .Ar expression @@ -57,6 +56,22 @@ the .Fn assert macro does nothing. .Pp +In all compilation modes, +.Fn assert +is defined as a macro with an ellipsis parameter, consistent with the +C23 standard. +This allows expressions containing commas to be passed directly without +requiring an extra pair of enclosing parentheses. +Only a single scalar expression is evaluated. +Supplying multiple arguments is prohibited, and hence are top-level comma +operators. +In particular, this guards against accidentally writing +.Fn assert +in the style of +.Fn static_assert , +which would otherwise silently evaluate as always true via the comma +operator. +.Pp The .Fn assert macro @@ -73,7 +88,7 @@ may be included multiple times. Each time whether or not .Dv NDEBUG is defined determines the behavior of assert from that point forward -until the end of the unit or another include of +until the end of the unit or another inclusion of .In assert.h . .Pp The @@ -82,9 +97,9 @@ macro should only be used for ensuring the developer's expectations hold true. It is not appropriate for regular run-time error detection. .Pp -The +In pre-C23 compilation modes .Fn static_assert -macro expands to +is implemented as a macro and expands to .Fn _Static_assert , and, contrarily to .Fn assert , @@ -94,8 +109,14 @@ message including the string literal message, if provided. The initial form of the .Fn _Static_assert containing a string literal message was introduced in C11 standard, and -the other form with no string literal is to be implemented by C2x and -some compilers may lack its adoption at present. +the other form with no string literal conforms to C23 standard. +.Pp +In C23 and later, +.Fn static_assert +is a language keyword, and +.Fn _Static_assert +is provided as an obsolescent alternative spelling that should not be +used for new code and development. .Sh EXAMPLES The assertion: .Dl "assert(1 == 0);" @@ -111,7 +132,20 @@ Second, the code will disappear if .Dv NDEBUG is defined, changing the semantics of the program. .Pp -The following asserts that the size of the S structure is 16. +The following example asserts that the +.Va iov_len +member of the compound literal, reflecting the value of +.Va len , +is non-zero. +The compound literal contains a comma that is not protected by +parentheses, which the variadic +.Fn assert +macro handles transparently: +.Dl assert((struct iovec){ buf, len }.iov_len); +.Pp +The following asserts that the size of the +.Vt S +structure is 16. Otherwise, it produces a diagnostic message which points at the constraint and includes the provided string literal: .Dl "static_assert(sizeof(struct S) == 16, ""size mismatch"");" @@ -123,14 +157,26 @@ If none is provided, it only points at the constraint. The .Fn assert macro conforms to -.St -isoC-99 . +.St -isoC-2023 . .Pp The .Fn static_assert macro conforms to .St -isoC-2011 . +In +.St -isoC-2023 , +it is a language keyword; whether the macro is defined or not +depends on compilation mode. .Sh HISTORY -An +The .Nm -macro appeared in +macro first appeared in .At v7 . +Starting with +.Fx 15.2 , +it accepts a variadic argument list, allowing expressions +containing commas, such as compound literals, to be passed +without requiring extra enclosing parentheses. +This conforms to +.St -isoC-2023 , +but made available in all compilation modes. diff --git a/share/man/man4/mac_do.4 b/share/man/man4/mac_do.4 index 8c08e072be88..7f05d5f88bf8 100644 --- a/share/man/man4/mac_do.4 +++ b/share/man/man4/mac_do.4 @@ -1,8 +1,8 @@ .\"- .\" SPDX-License-Identifier: BSD-2-Clause .\" -.\" Copyright (c) 2024 Baptiste Daroussin <bapt@FreeBSD.org> -.\" Copyright (c) 2024 The FreeBSD Foundation +.\" Copyright (c) 2024, Baptiste Daroussin <bapt@FreeBSD.org> +.\" Copyright (c) 2024, 2026, The FreeBSD Foundation .\" .\" Portions of this documentation were written by Olivier Certner .\" <olce@FreeBSD.org> at Kumacom SARL under sponsorship from the FreeBSD @@ -42,13 +42,23 @@ policy module allows unprivileged users to change process credentials according to rules configured by the administrator. It supports per-jail configuration. .Pp -Currently, the +The .Nm -policy module only produces effects to processes spawned from the +policy module only produces effects on processes spawned from specific +executables from a configurable whitelist. +By default, this whitelist only contains the .Pa /usr/bin/mdo executable, please see .Xr mdo 1 for more details on this program. +.Pp +Section +.Sx CREDENTIALS RULES +specifies the format of credentials transition rules, and section +.Sx CONFIGURATION +explains how to configure +.Nm , +including rules and authorized executables. .Sh CREDENTIALS RULES Rules specify which transitions of process credentials .Nm @@ -267,84 +277,170 @@ then converted to unsigned ones as specified in the C standard for the and .Vt gid_t types, which are both 32-bit unsigned integers. -.Sh RUNTIME CONFIGURATION -The following +.Sh CONFIGURATION +Each parameter of +.Nm +has a corresponding +.Xr sysctl 8 +knob. +.Nm +supports per-jail values for most parameters. +.Ss Sysctl Knobs +The .Xr sysctl 8 -knobs are available: +knobs presented by +.Nm +are of two types: Global ones, which influence all uses of the module, and +per-jail ones, which allow to retrieve or change the setting applicable to +a jail +.Pq or the host +from within. +They are tagged accordingly in the list below. +.Pp +The indicated default values for per-jail parameters applies to the host. +Those applying to jails are described in the +.Sx Jail Parameters +subsection below. +.Pp +The following knobs are available: .Bl -tag -width indent .It Va security.mac.do.enabled Enable the .Nm policy. -(Default: 1). -.It Va security.mac.do.rules -The list of credential rules, whose syntax is described in the -.Sx CREDENTIALS RULES -section above. -This list is specific to each jail. -Please see the -.Sx JAIL SUPPORT -section below for more details on the interaction of -.Nm -with jails. +.Pq Global. Default: 1. .It Va security.mac.do.print_parse_error Logs a message on trying to set incorrect rules via the .Va security.mac.do.rules .Xr sysctl 8 knob. +.Pq Global. Default: 1. +.It Va security.mac.do.rules +The list of credentials transition rules, whose syntax is described in the +.Sx CREDENTIALS RULES +section above. +An empty string effectively disables the policy. +.Pq Per-jail. Default: Empty. +.It Va security.mac.do.exec_paths +The list of absolute paths +.Pq relative to the current jail's root +to authorized executables, separated by colons +.Pq Ql ":" . +Only processes launched from these executables are considered by the +.Nm +policy. +An empty string effectively disables the policy. +.Po +Per-jail. Default: +.Ql "/usr/bin/mdo" . +.Pc .El -.Sh JAIL SUPPORT +.Ss Jail Parameters +Most parameters of .Nm -supports per-jail configuration of rules. +are per-jail +.Po +see the +.Sx "Sysctl Knobs" +subsection above +.Pc . +Those that are per-jail have corresponding jail parameters that can be used to +set their initial values on jail creation or modify their values in a running +jail from outside the jail. .Pp -By default, at creation, a new jail has no credentials rules, effectively -disabling +By default, as it is for the host, a new jail has .Nm -for its processes. +disabled for its processes, as if the +.Va mac.do +parameter below was explicitly set to +.Ql disable . .Pp -The following jail parameters are defined: +Each unspecified parameter other than +.Va mac.do +defaults to a copy of its value in the currently applicable configuration for +a running jail, or from the parent jail on jail creation. +.Pp +The following jail parameters are available: .Bl -tag -width indent .It Va mac.do Possible values are: +.Pp .Bl -tag -width "'disable'" -compact .It Ql new .Nm -will enforce specific credential rules in the jail. -The -.Va mac.do.rules -jail parameter must also be set in this case. +will use a specific configuration for the jail. +This case degrades to +.Ql disable +if one of the other jail parameters end up empty after applying the default +values rule +.Pq see the preamble . .It Ql disable Disables .Nm in the jail. -Strictly equivalent to jail creation's default behavior and to setting the rules -to an empty string. +This is achieved by ensuring that at least one of the +.Va mac.do.rules +and +.Va mac.do.exec_paths +jail parameters are empty. +If none of them ends up empty after applying the default values rule +.Pq see the preamble , +.Va mac.do.rules +is forced to an empty value. +An explicit +.Ql disable +is incompatible with explicit non-empty values for all other jail parameters and +will trigger an error. .It Ql inherit -The jail's credentials rules are inherited from the jail's parent +The other per-jail parameters are inherited from those applicable to the jail's +parent .Pq which may themselves have been inherited . -Modified rules propagate to all children jails configured for inheritance. +Configuration modifications immediately propagate to all descendant jails +configured for inheritance +.Po +as long as there is no intervening jail having its own specific configuration +.Pc . .El +.Pp +The default value depends on the absence or presence and value of the other jail +parameters. +As soon as one of the latter is present and not empty, the default value is +.Ql new , +else it is +.Ql disable . +Inheritance is never established implicitly, it must be explicitly requested. .It Va mac.do.rules The credentials rules for the jail. -It is always equal to the value that can be retrieved by the +See the description of the corresponding .Xr sysctl 8 knob .Va security.mac.do.rules -described in section -.Sx RUNTIME CONFIGURATION . -If set, and the jail parameter -.Va mac.do -is not so explicitly, the value of the latter will default to -.Ql disable -if empty, else to -.Ql new . +in subsection +.Sx "Sysctl Knobs" +above. +See also the preamble for the default values rule. +.It Va mac.do.exec_paths +The authorized executables. +See the description of the corresponding +.Xr sysctl 8 +knob +.Va security.mac.do.exec_paths +in subsection +.Sx "Sysctl Knobs" +above. +See also the preamble for the default values rule. .El +.Ss Consistency +Values read or set from jail parameters are always consistent with their +corresponding +.Xr sysctl 8 +knobs, effectively operating on the same internal +.Dq variable . .Pp -Each jail must have -.Xr mdo 1 -installed at path -.Pa /usr/bin/mdo , -as this path is currently not configurable. +All accesses to some parameter or some jail configuration as a whole, whether +a read or a modification, are sequentially consistent. +In other words, they appear to be atomic, and all threads see them happening in +the same order. .Sh EXAMPLES Here are several examples of single rules matching processes having a real user ID of 10001: @@ -405,6 +501,7 @@ current supplementary groups must be kept. .Sh AUTHORS .An Olivier Certner Aq Mt olce@FreeBSD.org .An Baptiste Daroussin Aq Mt bapt@FreeBSD.org +.An Kushagra Srivastava Aq Mt kushagra1403@gmail.com .Sh BUGS Currently, .Nm diff --git a/stand/defs.mk b/stand/defs.mk index 7f3803c7ab42..ac4f38451111 100644 --- a/stand/defs.mk +++ b/stand/defs.mk @@ -78,7 +78,7 @@ LIBSA= ${BOOTOBJ}/libsa/libsa.a .if ${MACHINE} == "i386" LIBSA32= ${LIBSA} .else -LIBSA32= ${BOOTOBJ}/libsa32/libsa32.a +LIBSA32= ${BOOTOBJ}/${"${LOADER}" == "loader_ia32":?efi/libsa32efi:libsa32}/libsa32.a .endif # Standard options: diff --git a/stand/efi/Makefile b/stand/efi/Makefile index 1887b9536a5b..5ece7eff8ef2 100644 --- a/stand/efi/Makefile +++ b/stand/efi/Makefile @@ -3,12 +3,18 @@ NO_OBJ=t .include <bsd.init.mk> SUBDIR.yes+= libefi -SUBDIR.${MK_LOADER_IA32}+= libefi32 +SUBDIR.${MK_LOADER_IA32}+= libsa32efi libefi32 SUBDIR.${MK_FDT}+= fdt SUBDIR.yes+= .WAIT SUBDIR.yes+= boot1 gptboot +.if ${LOADER_DEFAULT_INTERP} == "lua" +SUBDIR.${MK_LOADER_IA32}+= liblua32efi +.elif ${LOADER_DEFAULT_INTERP} == "4th" +SUBDIR.${MK_LOADER_IA32}+= ficl32efi +.endif + SUBDIR.${MK_FORTH}+= loader_4th SUBDIR.${MK_LOADER_LUA}+= loader_lua SUBDIR.${MK_LOADER_IA32}+= loader_ia32 diff --git a/stand/efi/Makefile.inc b/stand/efi/Makefile.inc index 6bb0af1d84f3..452820aeeb32 100644 --- a/stand/efi/Makefile.inc +++ b/stand/efi/Makefile.inc @@ -8,6 +8,11 @@ LDFLAGS+= -nostdlib .if ${MACHINE_CPUARCH} == "amd64" CFLAGS+= -fshort-wchar CFLAGS+= -mno-red-zone +.if ${DO32:U0} == 1 +# This is needed so the EDK2 EFI structs have the correct layout for +# the ia32 loader. +CFLAGS+= -malign-double +.endif .endif .if ${MACHINE_CPUARCH} == "aarch64" diff --git a/stand/efi/ficl32efi/Makefile b/stand/efi/ficl32efi/Makefile new file mode 100644 index 000000000000..63800cb0f209 --- /dev/null +++ b/stand/efi/ficl32efi/Makefile @@ -0,0 +1,3 @@ +DO32=1 + +.include "${.CURDIR}/../../ficl/Makefile" diff --git a/stand/efi/liblua32efi/Makefile b/stand/efi/liblua32efi/Makefile new file mode 100644 index 000000000000..cf391967ecf0 --- /dev/null +++ b/stand/efi/liblua32efi/Makefile @@ -0,0 +1,3 @@ +DO32=1 + +.include "${.CURDIR}/../../liblua/Makefile" diff --git a/stand/efi/libsa32efi/Makefile b/stand/efi/libsa32efi/Makefile new file mode 100644 index 000000000000..109c420bf734 --- /dev/null +++ b/stand/efi/libsa32efi/Makefile @@ -0,0 +1 @@ +.include "${.CURDIR}/../../libsa32/Makefile" diff --git a/stand/loader.mk b/stand/loader.mk index 496252e7a534..0d94ed3e6263 100644 --- a/stand/loader.mk +++ b/stand/loader.mk @@ -162,14 +162,14 @@ LIBFICL= ${BOOTOBJ}/ficl/libficl.a .if ${MACHINE} == "i386" LIBFICL32= ${LIBFICL} .else -LIBFICL32= ${BOOTOBJ}/ficl32/libficl.a +LIBFICL32= ${BOOTOBJ}/${"${LOADER}" == "loader_ia32":?efi/ficl32efi:ficl32}/libficl.a .endif LIBLUA= ${BOOTOBJ}/liblua/liblua.a .if ${MACHINE} == "i386" LIBLUA32= ${LIBLUA} .else -LIBLUA32= ${BOOTOBJ}/liblua32/liblua.a +LIBLUA32= ${BOOTOBJ}/${"${LOADER}" == "loader_ia32":?efi/liblua32efi:liblua32}/liblua.a .endif CLEANFILES+= vers.c diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index dbad85096a1d..8df4868f5312 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -1827,29 +1827,53 @@ wrmsr_early_safe_start(void) { struct region_descriptor efi_idt; struct gate_descriptor *gpf_descr; + int i; sidt(&wrmsr_early_safe_orig_efi_idt); efi_idt.rd_limit = 32 * sizeof(idt0[0]); efi_idt.rd_base = (uintptr_t)idt0; lidt(&efi_idt); - gpf_descr = &idt0[IDT_GP]; - gpf_descr->gd_looffset = (uintptr_t)wrmsr_early_safe_gp_handler; - gpf_descr->gd_hioffset = (uintptr_t)wrmsr_early_safe_gp_handler >> 16; - gpf_descr->gd_selector = rcs(); - gpf_descr->gd_type = SDT_SYSTGT; - gpf_descr->gd_p = 1; + /* Setup handler for all possible exceptions. */ + for (i = 0; i < 32; i++) { + gpf_descr = &idt0[i]; + gpf_descr->gd_looffset = + (uintptr_t)wrmsr_early_safe_gp_handler; + gpf_descr->gd_hioffset = + (uintptr_t)wrmsr_early_safe_gp_handler >> 16; + gpf_descr->gd_selector = rcs(); + gpf_descr->gd_type = SDT_SYSTGT; + gpf_descr->gd_p = 1; + } } void wrmsr_early_safe_end(void) { - struct gate_descriptor *gpf_descr; + int i; lidt(&wrmsr_early_safe_orig_efi_idt); - gpf_descr = &idt0[IDT_GP]; - memset_early(gpf_descr, 0, sizeof(*gpf_descr)); + for (i = 0; i < 32; i++) + memset_early(&idt0[i], 0, sizeof(idt0[0])); +} + +int +safe_read(vm_offset_t addr, char *valp) +{ + struct uio uio; + struct iovec iov; + + iov.iov_base = valp; + iov.iov_len = 1; + uio.uio_offset = addr; + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + uio.uio_resid = 1; + uio.uio_segflg = UIO_SYSSPACE; + uio.uio_rw = UIO_READ; + uio.uio_td = NULL; + return (uiomove_mem(UIO_MEM_KMEM, &uio)); } #ifdef KDB diff --git a/sys/amd64/amd64/mem.c b/sys/amd64/amd64/mem.c index ab1e6cde6cd5..7d1f0f42d01c 100644 --- a/sys/amd64/amd64/mem.c +++ b/sys/amd64/amd64/mem.c @@ -61,10 +61,6 @@ #include <machine/specialreg.h> #include <machine/vmparam.h> -#include <vm/vm.h> -#include <vm/pmap.h> -#include <vm/vm_extern.h> - #include <machine/memdev.h> /* @@ -72,99 +68,22 @@ */ MALLOC_DEFINE(M_MEMDESC, "memdesc", "memory range descriptors"); -/* ARGSUSED */ int memrw(struct cdev *dev, struct uio *uio, int flags) { - struct iovec *iov; - void *p, *vd; - ssize_t orig_resid; - vm_prot_t prot; - u_long v; - u_int c; - int error; - - error = 0; - orig_resid = uio->uio_resid; - while (uio->uio_resid > 0 && error == 0) { - iov = uio->uio_iov; - if (iov->iov_len == 0) { - uio->uio_iov++; - uio->uio_iovcnt--; - if (uio->uio_iovcnt < 0) - panic("memrw"); - continue; - } - v = uio->uio_offset; - c = ulmin(iov->iov_len, PAGE_SIZE - (u_int)(v & PAGE_MASK)); - - switch (dev2unit(dev)) { - case CDEV_MINOR_KMEM: - /* - * Since c is clamped to be less or equal than - * PAGE_SIZE, the uiomove() call does not - * access past the end of the direct map. - */ - if (v >= kva_layout.dmap_low && - v < kva_layout.dmap_high) { - error = uiomove((void *)v, c, uio); - break; - } - - switch (uio->uio_rw) { - case UIO_READ: - prot = VM_PROT_READ; - break; - case UIO_WRITE: - prot = VM_PROT_WRITE; - break; - } + enum uiomove_mem_req req; - if (!kernacc((void *)v, c, prot)) { - error = EFAULT; - break; - } - - /* - * If the extracted address is not accessible - * through the direct map, then we make a - * private (uncached) mapping because we can't - * depend on the existing kernel mapping - * remaining valid until the completion of - * uiomove(). - * - * XXX We cannot provide access to the - * physical page 0 mapped into KVA. - */ - v = pmap_extract(kernel_pmap, v); - if (v == 0) { - error = EFAULT; - break; - } - /* FALLTHROUGH */ - case CDEV_MINOR_MEM: - if (v < dmaplimit) { - vd = PHYS_TO_DMAP(v); - error = uiomove(vd, c, uio); - break; - } - if (v > cpu_getmaxphyaddr()) { - error = EFAULT; - break; - } - p = pmap_mapdev(v, PAGE_SIZE); - error = uiomove(p, c, uio); - pmap_unmapdev(p, PAGE_SIZE); - break; - } + switch (dev2unit(dev)) { + case CDEV_MINOR_KMEM: + req = UIO_MEM_KMEM; + break; + case CDEV_MINOR_MEM: + req = UIO_MEM_MEM; + break; + default: + __unreachable(); } - /* - * Don't return error if any byte was written. Read and write - * can return error only if no i/o was performed. - */ - if (uio->uio_resid != orig_resid) - error = 0; - return (error); + return (uiomove_mem(req, uio)); } /* diff --git a/sys/amd64/amd64/support.S b/sys/amd64/amd64/support.S index 09d4ef85b087..1d7d05843ba8 100644 --- a/sys/amd64/amd64/support.S +++ b/sys/amd64/amd64/support.S @@ -1566,20 +1566,19 @@ msr_onfault: ret ENTRY(wrmsr_early_safe) + movq %rsp,%r11 movl %edi,%ecx movl %esi,%eax sarq $32,%rsi movl %esi,%edx wrmsr xorl %eax,%eax -wrmsr_early_faulted: ret ENTRY(wrmsr_early_safe_gp_handler) - addq $8,%rsp + movq %r11,%rsp movl $EFAULT,%eax - movq $wrmsr_early_faulted,(%rsp) - iretq + ret /* * void pmap_pti_pcid_invalidate(uint64_t ucr3, uint64_t kcr3); diff --git a/sys/amd64/amd64/uio_machdep.c b/sys/amd64/amd64/uio_machdep.c index 16915bccf9f5..11e6ad2b1da9 100644 --- a/sys/amd64/amd64/uio_machdep.c +++ b/sys/amd64/amd64/uio_machdep.c @@ -44,9 +44,11 @@ #include <sys/uio.h> #include <vm/vm.h> +#include <vm/vm_extern.h> #include <vm/vm_page.h> #include <machine/vmparam.h> +#include <machine/md_var.h> /* * Implement uiomove(9) from physical memory using the direct map to @@ -141,3 +143,97 @@ out: td->td_pflags &= ~TDP_DEADLKTREAT; return (error); } + +int +uiomove_mem(enum uiomove_mem_req req, struct uio *uio) +{ + struct iovec *iov; + void *p, *vd; + ssize_t orig_resid; + vm_prot_t prot; + u_long v; + u_int c; + int error; + + error = 0; + orig_resid = uio->uio_resid; + while (uio->uio_resid > 0 && error == 0) { + iov = uio->uio_iov; + if (iov->iov_len == 0) { + uio->uio_iov++; + uio->uio_iovcnt--; + if (uio->uio_iovcnt < 0) + panic("memrw"); + continue; + } + v = uio->uio_offset; + c = ulmin(iov->iov_len, PAGE_SIZE - (u_int)(v & PAGE_MASK)); + + switch (req) { + case UIO_MEM_KMEM: + /* + * Since c is clamped to be less or equal than + * PAGE_SIZE, the uiomove() call does not + * access past the end of the direct map. + */ + if (v >= kva_layout.dmap_low && + v < kva_layout.dmap_high) { + error = uiomove((void *)v, c, uio); + break; + } + + switch (uio->uio_rw) { + case UIO_READ: + prot = VM_PROT_READ; + break; + case UIO_WRITE: + prot = VM_PROT_WRITE; + break; + } + + if (!kernacc((void *)v, c, prot)) { + error = EFAULT; + break; + } + + /* + * If the extracted address is not accessible + * through the direct map, then we make a + * private (uncached) mapping because we can't + * depend on the existing kernel mapping + * remaining valid until the completion of + * uiomove(). + * + * XXX We cannot provide access to the + * physical page 0 mapped into KVA. + */ + v = pmap_extract(kernel_pmap, v); + if (v == 0) { + error = EFAULT; + break; + } + /* FALLTHROUGH */ + case UIO_MEM_MEM: + if (v < dmaplimit) { + vd = PHYS_TO_DMAP(v); + error = uiomove(vd, c, uio); + break; + } + if (v > cpu_getmaxphyaddr()) { + error = EFAULT; + break; + } + p = pmap_mapdev(v, PAGE_SIZE); + error = uiomove(p, c, uio); + pmap_unmapdev(p, PAGE_SIZE); + break; + } + } + /* + * Don't return error if any byte was written. Read and write + * can return error only if no i/o was performed. + */ + if (uio->uio_resid != orig_resid) + error = 0; + return (error); +} diff --git a/sys/amd64/include/md_var.h b/sys/amd64/include/md_var.h index 4b98c5d8c418..0e8fe916490b 100644 --- a/sys/amd64/include/md_var.h +++ b/sys/amd64/include/md_var.h @@ -106,6 +106,12 @@ void wrmsr_early_safe_start(void); void wrmsr_early_safe_end(void); int wrmsr_early_safe(u_int msr, uint64_t data); +enum uiomove_mem_req { + UIO_MEM_KMEM = 101, + UIO_MEM_MEM, +}; +int uiomove_mem(enum uiomove_mem_req req, struct uio *uio); + #endif /* !_MACHINE_MD_VAR_H_ */ #endif /* __i386__ */ diff --git a/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c b/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c index e0c4327d8e05..6e974a1a61bb 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c @@ -365,6 +365,7 @@ bcm_sdhci_attach(device_t dev) return (0); fail: + bcm_dma_free(sc->sc_dma_ch); if (sc->sc_intrhand) bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_intrhand); if (sc->sc_irq_res) diff --git a/sys/arm64/rockchip/rk_gpio.c b/sys/arm64/rockchip/rk_gpio.c index 8da37d516802..7c2071d2d178 100644 --- a/sys/arm64/rockchip/rk_gpio.c +++ b/sys/arm64/rockchip/rk_gpio.c @@ -227,8 +227,22 @@ rk_gpio_intr(void *arg) status &= ~(1 << pin); if (intr_isrc_dispatch(RK_GPIO_ISRC(sc, pin), tf)) { - device_printf(sc->sc_dev, "Interrupt pin=%d unhandled\n", - pin); + /* + * Pin asserted but no consumer is registered for it + * yet (or anymore). Level-triggered sources keep + * firing on every interrupt cycle, so a single stuck + * pin floods the console with thousands of these + * messages per second. Mask the pin's IRQ at the + * controller and disable further dispatches; if a + * consumer attaches later it will re-enable through + * pic_enable_intr / rk_gpio_pic_enable_intr. + */ + RK_GPIO_LOCK(sc); + rk_gpio_write_bit(sc, RK_GPIO_INTMASK, pin, 1); + rk_gpio_write_bit(sc, RK_GPIO_INTEN, pin, 0); + RK_GPIO_UNLOCK(sc); + device_printf(sc->sc_dev, + "Interrupt pin=%d unhandled โ masked\n", pin); continue; } @@ -818,10 +832,14 @@ rk_pic_setup_intr(device_t dev, struct intr_irqsrc *isrc, return (EINVAL); } rk_gpio_write_bit(sc, RK_GPIO_DEBOUNCE, pin, 1); - rk_gpio_write_bit(sc, RK_GPIO_INTMASK, pin, 0); - rk_gpio_write_bit(sc, RK_GPIO_INTEN, pin, 1); RK_GPIO_UNLOCK(sc); + /* + * Leave the interrupt masked + disabled here. INTRNG will call + * pic_enable_intr() next to make it live. That keeps the + * masking responsibility cleanly in enable/disable rather than + * split between setup and disable. + */ return (0); } @@ -837,14 +855,86 @@ rk_pic_teardown_intr(device_t dev, struct intr_irqsrc *isrc, if (isrc->isrc_handlers == 0) { irqsrc->mode = GPIO_INTR_CONFORM; RK_GPIO_LOCK(sc); - rk_gpio_write_bit(sc, RK_GPIO_INTEN, irqsrc->irq, 0); - rk_gpio_write_bit(sc, RK_GPIO_INTMASK, irqsrc->irq, 0); + /* + * INTEN/INTMASK are already cleared by pic_disable_intr, + * which INTRNG calls before teardown of the last handler. + * We only need to undo what setup_intr configured -- here, + * the debounce filter. + */ rk_gpio_write_bit(sc, RK_GPIO_DEBOUNCE, irqsrc->irq, 0); RK_GPIO_UNLOCK(sc); } return (0); } +/* + * INTRNG calls pic_disable_intr() during teardown of the final handler + * for a source, OR when a consumer explicitly wants the source off. + * Clear INTEN so the controller will not raise this pin at all. + * + * The in-flight masking between FILTER_SCHEDULE_THREAD and ithread + * completion is handled by pic_pre_ithread() / pic_post_ithread() + * below, NOT by this method. + */ +static void +rk_pic_disable_intr(device_t dev, struct intr_irqsrc *isrc) +{ + struct rk_gpio_softc *sc = device_get_softc(dev); + struct rk_pin_irqsrc *rkisrc = (struct rk_pin_irqsrc *)isrc; + + RK_GPIO_LOCK(sc); + rk_gpio_write_bit(sc, RK_GPIO_INTMASK, rkisrc->irq, 1); + rk_gpio_write_bit(sc, RK_GPIO_INTEN, rkisrc->irq, 0); + RK_GPIO_UNLOCK(sc); +} + +/* + * INTRNG calls pic_enable_intr() to make a source live for the first + * time (after setup_intr), or to re-enable after a prior + * pic_disable_intr(). Set INTEN and unmask so the controller starts + * delivering this pin. + */ +static void +rk_pic_enable_intr(device_t dev, struct intr_irqsrc *isrc) +{ + struct rk_gpio_softc *sc = device_get_softc(dev); + struct rk_pin_irqsrc *rkisrc = (struct rk_pin_irqsrc *)isrc; + + RK_GPIO_LOCK(sc); + rk_gpio_write_bit(sc, RK_GPIO_INTEN, rkisrc->irq, 1); + rk_gpio_write_bit(sc, RK_GPIO_INTMASK, rkisrc->irq, 0); + RK_GPIO_UNLOCK(sc); +} + +/* + * Called by INTRNG before delivering to the ithread. Mask the source + * so it cannot re-fire during the ithread window -- without this, + * level-low IRQs (e.g. FUSB302 INT_N) re-trigger continuously and + * starve the ithread (~210 kHz storm observed via dtrace). + * Re-unmasked in pic_post_ithread() once the ithread acks the source. + */ +static void +rk_pic_pre_ithread(device_t dev, struct intr_irqsrc *isrc) +{ + struct rk_gpio_softc *sc = device_get_softc(dev); + struct rk_pin_irqsrc *rkisrc = (struct rk_pin_irqsrc *)isrc; + + RK_GPIO_LOCK(sc); + rk_gpio_write_bit(sc, RK_GPIO_INTMASK, rkisrc->irq, 1); + RK_GPIO_UNLOCK(sc); +} + +static void +rk_pic_post_ithread(device_t dev, struct intr_irqsrc *isrc) +{ + struct rk_gpio_softc *sc = device_get_softc(dev); + struct rk_pin_irqsrc *rkisrc = (struct rk_pin_irqsrc *)isrc; + + RK_GPIO_LOCK(sc); + rk_gpio_write_bit(sc, RK_GPIO_INTMASK, rkisrc->irq, 0); + RK_GPIO_UNLOCK(sc); +} + static device_method_t rk_gpio_methods[] = { /* Device interface */ DEVMETHOD(device_probe, rk_gpio_probe), @@ -873,6 +963,10 @@ static device_method_t rk_gpio_methods[] = { DEVMETHOD(pic_map_intr, rk_pic_map_intr), DEVMETHOD(pic_setup_intr, rk_pic_setup_intr), DEVMETHOD(pic_teardown_intr, rk_pic_teardown_intr), + DEVMETHOD(pic_disable_intr, rk_pic_disable_intr), + DEVMETHOD(pic_enable_intr, rk_pic_enable_intr), + DEVMETHOD(pic_pre_ithread, rk_pic_pre_ithread), + DEVMETHOD(pic_post_ithread, rk_pic_post_ithread), /* ofw_bus interface */ DEVMETHOD(ofw_bus_get_node, rk_gpio_get_node), diff --git a/sys/cam/ctl/scsi_ctl.c b/sys/cam/ctl/scsi_ctl.c index 68f1cabf6d07..6a55aba2669b 100644 --- a/sys/cam/ctl/scsi_ctl.c +++ b/sys/cam/ctl/scsi_ctl.c @@ -522,7 +522,8 @@ ctlferegister(struct cam_periph *periph, void *arg) new_ccb->ccb_h.io_ptr = new_io; LIST_INSERT_HEAD(&softc->atio_list, &new_ccb->ccb_h, periph_links.le); - xpt_setup_ccb(&new_ccb->ccb_h, periph->path, CAM_PRIORITY_NONE); + xpt_setup_ccb(&new_ccb->ccb_h, periph->path, + CAM_PRIORITY_NORMAL); new_ccb->ccb_h.func_code = XPT_ACCEPT_TARGET_IO; new_ccb->ccb_h.cbfcnp = ctlfedone; new_ccb->ccb_h.flags |= CAM_UNLOCKED; @@ -569,7 +570,8 @@ ctlferegister(struct cam_periph *periph, void *arg) new_ccb->ccb_h.io_ptr = new_io; LIST_INSERT_HEAD(&softc->inot_list, &new_ccb->ccb_h, periph_links.le); - xpt_setup_ccb(&new_ccb->ccb_h, periph->path, CAM_PRIORITY_NONE); + xpt_setup_ccb(&new_ccb->ccb_h, periph->path, + CAM_PRIORITY_NORMAL); new_ccb->ccb_h.func_code = XPT_IMMEDIATE_NOTIFY; new_ccb->ccb_h.cbfcnp = ctlfedone; new_ccb->ccb_h.flags |= CAM_UNLOCKED; @@ -1003,7 +1005,7 @@ ctlfe_requeue_ccb(struct cam_periph *periph, union ccb *ccb, int unlock) * target/lun. Reset the target and LUN fields back to the wildcard * values before we send them back down to the SIM. */ - xpt_setup_ccb_flags(&ccb->ccb_h, periph->path, CAM_PRIORITY_NONE, + xpt_setup_ccb_flags(&ccb->ccb_h, periph->path, CAM_PRIORITY_NORMAL, ccb->ccb_h.flags); xpt_action(ccb); diff --git a/sys/compat/linux/linux_mmap.c b/sys/compat/linux/linux_mmap.c index a8e790a29da4..9fecb6ebb2ad 100644 --- a/sys/compat/linux/linux_mmap.c +++ b/sys/compat/linux/linux_mmap.c @@ -63,6 +63,10 @@ static int linux_mmap_check_fp(struct file *fp, int flags, int prot, int maxprot) { + /* Linux returns EBADF if mmap() is called on an O_PATH file descriptor */ + if (fp->f_ops == &path_fileops) + return (EBADF); + /* Linux mmap() just fails for O_WRONLY files */ if ((fp->f_flag & FREAD) == 0) return (EACCES); diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c b/sys/compat/linuxkpi/common/src/linux_80211.c index cade61e8446f..901c59702840 100644 --- a/sys/compat/linuxkpi/common/src/linux_80211.c +++ b/sys/compat/linuxkpi/common/src/linux_80211.c @@ -1607,12 +1607,13 @@ lkpi_iv_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k) } sta = LSTA_TO_STA(lsta); - keylen = k->wk_keylen; + keylen = ieee80211_crypto_get_key_len(k); lcipher = lkpi_net80211_to_l80211_cipher_suite( - k->wk_cipher->ic_cipher, k->wk_keylen); + k->wk_cipher->ic_cipher, ieee80211_crypto_get_key_len(k)); switch (lcipher) { case WLAN_CIPHER_SUITE_TKIP: - keylen += 2 * k->wk_cipher->ic_miclen; + keylen += ieee80211_crypto_get_key_txmic_len(k); + keylen += ieee80211_crypto_get_key_rxmic_len(k); break; case WLAN_CIPHER_SUITE_CCMP: case WLAN_CIPHER_SUITE_GCMP: @@ -1643,8 +1644,9 @@ lkpi_iv_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k) kc->hw_key_idx = /* set by hw and needs to be passed for TX */; #endif atomic64_set(&kc->tx_pn, k->wk_keytsc); - kc->keylen = k->wk_keylen; - memcpy(kc->key, k->wk_key, k->wk_keylen); + kc->keylen = ieee80211_crypto_get_key_len(k); + memcpy(kc->key, ieee80211_crypto_get_key_data(k), + ieee80211_crypto_get_key_len(k)); if (k->wk_flags & (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV)) kc->flags |= IEEE80211_KEY_FLAG_PAIRWISE; @@ -1656,8 +1658,12 @@ lkpi_iv_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k) switch (kc->cipher) { case WLAN_CIPHER_SUITE_TKIP: - memcpy(kc->key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY, k->wk_txmic, k->wk_cipher->ic_miclen); - memcpy(kc->key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY, k->wk_rxmic, k->wk_cipher->ic_miclen); + memcpy(kc->key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY, + ieee80211_crypto_get_key_txmic_data(k), + ieee80211_crypto_get_key_txmic_len(k)); + memcpy(kc->key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY, + ieee80211_crypto_get_key_rxmic_data(k), + ieee80211_crypto_get_key_rxmic_len(k)); break; case WLAN_CIPHER_SUITE_CCMP: case WLAN_CIPHER_SUITE_GCMP: @@ -5531,10 +5537,10 @@ lkpi_hw_crypto_prepare_tkip(struct ieee80211_key *k, * "enmic" (though we do not do that). */ /* any conditions to not apply this? */ - if (skb_tailroom(skb) < k->wk_cipher->ic_miclen) + if (skb_tailroom(skb) < ieee80211_crypto_get_key_txmic_len(k)) return (ENOBUFS); - p = skb_put(skb, k->wk_cipher->ic_miclen); + p = skb_put(skb, ieee80211_crypto_get_key_txmic_len(k)); if ((kc->flags & IEEE80211_KEY_FLAG_PUT_MIC_SPACE) != 0) goto encrypt; diff --git a/sys/contrib/edk2/Include/Base.h b/sys/contrib/edk2/Include/Base.h index 3ae798db8429..d3342c9a6ca2 100644 --- a/sys/contrib/edk2/Include/Base.h +++ b/sys/contrib/edk2/Include/Base.h @@ -841,10 +841,8 @@ STATIC_ASSERT (ALIGNOF (INT16) == sizeof (INT16), "Alignment of INT16 does not STATIC_ASSERT (ALIGNOF (UINT16) == sizeof (UINT16), "Alignment of UINT16 does not meet UEFI Specification Data Type requirements"); STATIC_ASSERT (ALIGNOF (INT32) == sizeof (INT32), "Alignment of INT32 does not meet UEFI Specification Data Type requirements"); STATIC_ASSERT (ALIGNOF (UINT32) == sizeof (UINT32), "Alignment of UINT32 does not meet UEFI Specification Data Type requirements"); -#ifndef _STANDALONE STATIC_ASSERT (ALIGNOF (INT64) == sizeof (INT64), "Alignment of INT64 does not meet UEFI Specification Data Type requirements"); STATIC_ASSERT (ALIGNOF (UINT64) == sizeof (UINT64), "Alignment of UINT64 does not meet UEFI Specification Data Type requirements"); -#endif STATIC_ASSERT (ALIGNOF (CHAR8) == sizeof (CHAR8), "Alignment of CHAR8 does not meet UEFI Specification Data Type requirements"); STATIC_ASSERT (ALIGNOF (CHAR16) == sizeof (CHAR16), "Alignment of CHAR16 does not meet UEFI Specification Data Type requirements"); STATIC_ASSERT (ALIGNOF (INTN) == sizeof (INTN), "Alignment of INTN does not meet UEFI Specification Data Type requirements"); diff --git a/sys/dev/bnxt/bnxt_en/bnxt_sriov.c b/sys/dev/bnxt/bnxt_en/bnxt_sriov.c index 270c18165fb7..071feffbadfd 100644 --- a/sys/dev/bnxt/bnxt_en/bnxt_sriov.c +++ b/sys/dev/bnxt/bnxt_en/bnxt_sriov.c @@ -7,6 +7,8 @@ #include "bnxt_hwrm.h" #include "bnxt_sriov.h" +#ifdef PCI_IOV + static int bnxt_set_vf_admin_mac(struct bnxt_softc *softc, struct bnxt_vf_info *vf, const uint8_t *mac) @@ -973,6 +975,43 @@ void bnxt_sriov_attach(struct bnxt_softc *softc) device_printf(dev, "Failed to initialize SR-IOV (error=%d)\n", rc); } +#else + +void +bnxt_sriov_attach(struct bnxt_softc *softc __unused) +{ +} + +int +bnxt_cfg_hw_sriov(struct bnxt_softc *softc __unused, + uint16_t *num_vfs __unused, bool reset __unused) +{ + return (0); +} + +int +bnxt_approve_mac(struct bnxt_softc *sc __unused) +{ + return (0); +} + +void +bnxt_hwrm_exec_fwd_req(struct bnxt_softc *softc __unused) +{ +} + +bool +bnxt_promisc_ok(struct bnxt_softc *softc __unused) +{ + return (true); +} + +void +bnxt_update_vf_mac(struct bnxt_softc *sc __unused) +{ +} +#endif + void bnxt_reenable_sriov(struct bnxt_softc *bp) { if (BNXT_PF(bp)) { diff --git a/sys/dev/bnxt/bnxt_en/bnxt_sriov.h b/sys/dev/bnxt/bnxt_en/bnxt_sriov.h index 176f54af0aa8..24ea11f29b83 100644 --- a/sys/dev/bnxt/bnxt_en/bnxt_sriov.h +++ b/sys/dev/bnxt/bnxt_en/bnxt_sriov.h @@ -8,10 +8,6 @@ #include "opt_global.h" #include "bnxt.h" -#ifndef PCI_IOV -#define PCI_IOV 1 -#endif - /* macro definations */ #define BNXT_MAX_VFS 4 diff --git a/sys/dev/bnxt/bnxt_en/if_bnxt.c b/sys/dev/bnxt/bnxt_en/if_bnxt.c index 6618016f3932..6d82302615e1 100644 --- a/sys/dev/bnxt/bnxt_en/if_bnxt.c +++ b/sys/dev/bnxt/bnxt_en/if_bnxt.c @@ -2875,11 +2875,9 @@ bnxt_attach_post(if_ctx_t ctx) bnxt_dcb_init(softc); bnxt_rdma_aux_device_init(softc); -#if PCI_IOV /* SR-IOV attach */ if (BNXT_PF(softc) && BNXT_CHIP_P5_PLUS(softc)) bnxt_sriov_attach(softc); -#endif failed: return rc; diff --git a/sys/dev/cxgbe/adapter.h b/sys/dev/cxgbe/adapter.h index 24a482b74dfb..8c5cf052b689 100644 --- a/sys/dev/cxgbe/adapter.h +++ b/sys/dev/cxgbe/adapter.h @@ -194,6 +194,7 @@ enum { IHF_CLR_ALL_SET = (1 << 5), /* Clear all set bits */ IHF_CLR_ALL_UNIGNORED = (1 << 6), /* Clear all unignored bits */ IHF_RUN_ALL_ACTIONS = (1 << 7), /* As if all cause are set */ + IHF_CLR_DELAYED = (1 << 9), /* Cleared in a delayed call */ }; #define IS_DETACHING(vi) ((vi)->flags & VI_DETACHING) diff --git a/sys/dev/cxgbe/common/t4_hw.c b/sys/dev/cxgbe/common/t4_hw.c index f4eef54e5c6b..41606201ad39 100644 --- a/sys/dev/cxgbe/common/t4_hw.c +++ b/sys/dev/cxgbe/common/t4_hw.c @@ -4794,6 +4794,27 @@ struct intr_info { const struct intr_action *actions; }; +/* Helper to clear interrupts that have IHF_CLR_DELAYED. */ +static void +clear_int_cause_reg(struct adapter *sc, const struct intr_info *ii, int flags) +{ + u32 cause, ucause; + + cause = ucause = t4_read_reg(sc, ii->cause_reg); + if (cause == 0) + return; + flags |= ii->flags; + if (flags & IHF_IGNORE_IF_DISABLED) + ucause &= t4_read_reg(sc, ii->enable_reg); + if (flags & IHF_CLR_ALL_SET) { + t4_write_reg(sc, ii->cause_reg, cause); + (void)t4_read_reg(sc, ii->cause_reg); + } else if (ucause != 0 && flags & IHF_CLR_ALL_UNIGNORED) { + t4_write_reg(sc, ii->cause_reg, ucause); + (void)t4_read_reg(sc, ii->cause_reg); + } +} + static inline char intr_alert_char(u32 cause, u32 enable, u32 fatal) { @@ -4869,8 +4890,8 @@ t4_handle_intr(struct adapter *sc, const struct intr_info *ii, uint32_t acause, } } - /* clear */ - if (cause != 0) { + /* Clear here unless delayed clear is requested. */ + if (cause != 0 && (flags & IHF_CLR_DELAYED) == 0) { if (flags & IHF_CLR_ALL_SET) { t4_write_reg(sc, ii->cause_reg, cause); (void)t4_read_reg(sc, ii->cause_reg); @@ -5003,22 +5024,63 @@ static bool pcie_intr_handler(struct adapter *adap, int arg, int flags) .details = NULL, .actions = NULL, }; + static const struct intr_details pcie_intr_cause_ext_details[] = { + { F_IPFORMQPERR, "PCIe IP FormQ Buffer PERR" }, + { F_IPFORMQCERR, "PCIe IP FormQ Buffer CERR" }, + { F_TRGT1GRPCERR, "TRGT1 Group FIFOs CERR" }, + { F_IPSOTCERR, "PCIe IP SOT Buffer SRAM CERR" }, + { F_IPRETRYCERR, "PCIe IP Replay Buffer CERR" }, + { F_IPRXDATAGRPCERR, "PCIe IP Rx Data Group SRAMs CERR" }, + { F_IPRXHDRGRPCERR, "PCIe IP Rx Header Group SRAMs CERR" }, + { F_A0ARBRSPORDFIFOPERR, "A0 Arbiter Response Order FIFO Parity Error" }, + { F_HRSPCERR, "Master HMA Channel Response Data SRAM CERR" }, + { F_HREQRDCERR, "Master HMA Channel Read Request SRAM CERR" }, + { F_HREQWRCERR, "Master HMA Channel Write Request SRAM CERR" }, + { F_DRSPCERR, "Master DMA Channel Response Data SRAM CERR" }, + { F_DREQRDCERR, "Master DMA Channel Read Request SRAM CERR" }, + { F_DREQWRCERR, "Master DMA Channel Write Request SRAM CERR" }, + { F_CRSPCERR, "Master CMD Channel Response Data SRAM CERR" }, + { F_ARSPPERR, "Master ARM Channel Response Data SRAM PERR" }, + { F_AREQRDPERR, "Master ARM Channel Read Request SRAM PERR" }, + { F_AREQWRPERR, "Master ARM Channel Write Request SRAM PERR" }, + { F_PIOREQGRPCERR, "PIO Request Group FIFOs CERR" }, + { F_ARSPCERR, "Master ARM Channel Response Data SRAM CERR" }, + { F_AREQRDCERR, "Master ARM Channel Read Request SRAM CERR" }, + { F_AREQWRCERR, "Master ARM Channel Write Request SRAM CERR" }, + { F_MARSPPERR, "INIC MA Ctrl and Data Rsp Perr" }, + { F_INICMAWDATAORDPERR, "INIC Ma Arb Write Ord Data Fifo Perr" }, + { F_EMUPERR, "CFG EMU SRAM PERR" }, + { F_ERRSPPERR, "CFG EMU SRAM CERR" }, + { F_MSTGRPCERR, "Master Data Path and Response Read Queue SRAM CERR" }, + { 0 } + }; struct intr_info pcie_int_cause_ext = { .name = "PCIE_INT_CAUSE_EXT", .cause_reg = A_PCIE_INT_CAUSE_EXT, .enable_reg = A_PCIE_INT_ENABLE_EXT, .fatal = 0, .flags = 0, - .details = NULL, + .details = pcie_intr_cause_ext_details, .actions = NULL, }; + static const struct intr_details pcie_intr_cause_x8_details[] = { + { F_X8TGTGRPPERR, "x8 TGT Group FIFOs parity error" }, + { F_X8IPSOTPERR, "PCIe x8 IP SOT Buffer SRAM PERR" }, + { F_X8IPRETRYPERR, "PCIe x8 IP Replay Buffer PERR" }, + { F_X8IPRXDATAGRPPERR, "PCIe x8 IP Rx Data Group SRAMs PERR" }, + { F_X8IPRXHDRGRPPERR, "PCIe x8 IP Rx Header Group SRAMs PERR" }, + { F_X8IPCORECERR, "x8 IP SOT, Retry, RxData, RxHdr SRAM CERR" }, + { F_X8MSTGRPPERR, "x8 Master Data Path and Response Read Queue SRAM PERR" }, + { F_X8MSTGRPCERR, "x8 Master Data Path and Response Read Queue SRAM CERR" }, + { 0 } + }; struct intr_info pcie_int_cause_x8 = { .name = "PCIE_INT_CAUSE_X8", .cause_reg = A_PCIE_INT_CAUSE_X8, .enable_reg = A_PCIE_INT_ENABLE_X8, .fatal = 0, .flags = 0, - .details = NULL, + .details = pcie_intr_cause_x8_details, .actions = NULL, }; bool fatal = false; @@ -5050,80 +5112,247 @@ static bool tp_intr_handler(struct adapter *adap, int arg, int flags) { F_FLMTXFLSTEMPTY, "TP out of Tx pages" }, { 0 } }; - static const struct intr_info tp_intr_info = { + static const struct intr_details t7_tp_intr_details[] = { + { F_FLMTXFLSTEMPTY, "Offload memory manager Tx free list empty" }, + { F_TPCERR, "TP modules flagged Correctable Error" }, + { F_OTHERPERR, "TP Other modules (Core, TM, FLM, MMGR, DB) Parity Error" }, + { F_TPEING1PERR, "TP-ESide Ingress1 Parity Error" }, + { F_TPEING0PERR, "TP-ESide Ingress0 Parity Error" }, + { F_TPEEGPERR, "TP-ESide Egress Parity Error" }, + { F_TPCPERR, "TP-CSide Parity Error" }, + { 0 } + }; + struct intr_info tp_intr_info = { .name = "TP_INT_CAUSE", .cause_reg = A_TP_INT_CAUSE, .enable_reg = A_TP_INT_ENABLE, .fatal = 0x7fffffff, - .flags = IHF_FATAL_IFF_ENABLED, - .details = tp_intr_details, + .flags = IHF_FATAL_IFF_ENABLED | IHF_CLR_DELAYED, + .details = NULL, .actions = NULL, }; - static const struct intr_info tp_inic_perr_cause = { - .name = "TP_INIC_PERR_CAUSE", - .cause_reg = A_TP_INIC_PERR_CAUSE, - .enable_reg = A_TP_INIC_PERR_ENABLE, + static const struct intr_details tp_cerr_cause_details[] = { + { F_TPCEGDATAFIFO, "TPCSide Egress Data FIFO" }, + { F_TPCLBKDATAFIFO, "TPCSide Loopback Data FIFO" }, + { F_RSSLKPSRAM, "RSS Lookup SRAM" }, + { F_SRQSRAM, "SRQ SRAM" }, + { F_ARPDASRAM, "ARP DA SRAM" }, + { F_ARPSASRAM, "ARP SA SRAM" }, + { F_ARPGRESRAM, "ARP GRE SRAM" }, + { F_ARPIPSECSRAM1, "ARP IPSec SRAM0" }, + { F_ARPIPSECSRAM0, "ARP IPSec SRAM1" }, + { 0 } + }; + static const struct intr_info tp_cerr_cause = { + .name = "TP_CERR_CAUSE", + .cause_reg = A_TP_CERR_CAUSE, + .enable_reg = A_TP_CERR_ENABLE, .fatal = 0xffffffff, .flags = IHF_FATAL_IFF_ENABLED, - .details = NULL, + .details = tp_cerr_cause_details, .actions = NULL, }; + static const struct intr_details tp_c_perr_details[] = { + { F_DMXFIFOOVFL, "Demux FIFO Overflow" }, + { F_URX2TPCDDPINTF, "ULPRX to TPC DDP Interface and FIFO" }, + { F_TPCDISPTOKENFIFO, "TPC Dispatch Token FIFO" }, + { F_TPCDISPCPLFIFO3, "TPC Dispatch CPL FIFO Ch3" }, + { F_TPCDISPCPLFIFO2, "TPC Dispatch CPL FIFO Ch2" }, + { F_TPCDISPCPLFIFO1, "TPC Dispatch CPL FIFO Ch1" }, + { F_TPCDISPCPLFIFO0, "TPC Dispatch CPL FIFO Ch0" }, + { F_URXPLDINTFCRC3, "ULPRX to TPC Payload Interface CRC Error Ch3" }, + { F_URXPLDINTFCRC2, "ULPRX to TPC Payload Interface CRC Error Ch2" }, + { F_URXPLDINTFCRC1, "ULPRX to TPC Payload Interface CRC Error Ch1" }, + { F_URXPLDINTFCRC0, "ULPRX to TPC Payload Interface CRC Error Ch0" }, + { F_DMXDBFIFO, "Demux DB FIFO" }, + { F_DMXDBSRAM, "Demux DB SRAM" }, + { F_DMXCPLFIFO, "Demux CPL FIFO" }, + { F_DMXCPLSRAM, "Demux CPL SRAM" }, + { F_DMXCSUMFIFO, "Demux Checksum FIFO" }, + { F_DMXLENFIFO, "Demux Length FIFO" }, + { F_DMXCHECKFIFO, "Demux Check CRC16 FIFO" }, + { F_DMXWINFIFO, "Demux Winner FIFO" }, + { F_EGTOKENFIFO, "Egress Token FIFO Parity Error" }, + { F_EGDATAFIFO, "Egress FIFO Parity Error" }, + { F_UTX2TPCINTF3, "ULPTX to TPC Interface Parity Error Ch3" }, + { F_UTX2TPCINTF2, "ULPTX to TPC Interface Parity Error Ch2" }, + { F_UTX2TPCINTF1, "ULPTX to TPC Interface Parity Error Ch1" }, + { F_UTX2TPCINTF0, "ULPTX to TPC Interface Parity Error Ch0" }, + { F_LBKTOKENFIFO, "Loopback Token FIFO Parity Error" }, + { F_LBKDATAFIFO, "Loopback FIFO Parity Error" }, + { 0 } + }; static const struct intr_info tp_c_perr_cause = { .name = "TP_C_PERR_CAUSE", .cause_reg = A_TP_C_PERR_CAUSE, .enable_reg = A_TP_C_PERR_ENABLE, .fatal = 0xffffffff, .flags = IHF_FATAL_IFF_ENABLED, - .details = NULL, + .details = tp_c_perr_details, .actions = NULL, }; + static const struct intr_details tp_e_eg_perr_details[] = { + { F_MPSLPBKTOKENFIFO, "MPS Loopback Token FIFO parity error" }, + { F_MPSMACTOKENFIFO, "MPS MAC Token FIFO parity error" }, + { F_DISPIPSECFIFO3, "Ch3 Dispatch IPSec FIFO parity error" }, + { F_DISPTCPFIFO3, "Ch3 Dispatch TCP FIFO parity error" }, + { F_DISPIPFIFO3, "Ch3 Dispatch IP FIFO parity error" }, + { F_DISPETHFIFO3, "Ch3 Dispatch ETH FIFO parity error" }, + { F_DISPGREFIFO3, "Ch3 Dispatch GRE FIFO parity error" }, + { F_DISPCPL5FIFO3, "Ch3 Dispatch CPL5 FIFO parity error" }, + { F_DISPIPSECFIFO2, "Ch2 Dispatch IPSec FIFO parity error" }, + { F_DISPTCPFIFO2, "Ch2 Dispatch TCP FIFO parity error" }, + { F_DISPIPFIFO2, "Ch2 Dispatch IP FIFO parity error" }, + { F_DISPETHFIFO2, "Ch2 Dispatch ETH FIFO parity error" }, + { F_DISPGREFIFO2, "Ch2 Dispatch GRE FIFO parity error" }, + { F_DISPCPL5FIFO2, "Ch2 Dispatch CPL5 FIFO parity error" }, + { F_DISPIPSECFIFO1, "Ch1 Dispatch IPSec FIFO parity error" }, + { F_DISPTCPFIFO1, "Ch1 Dispatch TCP FIFO parity error" }, + { F_DISPIPFIFO1, "Ch1 Dispatch IP FIFO parity error" }, + { F_DISPETHFIFO1, "Ch1 Dispatch ETH FIFO parity error" }, + { F_DISPGREFIFO1, "Ch1 Dispatch GRE FIFO parity error" }, + { F_DISPCPL5FIFO1, "Ch1 Dispatch CPL5 FIFO parity error" }, + { F_DISPIPSECFIFO0, "Ch0 Dispatch IPSec FIFO parity error" }, + { F_DISPTCPFIFO0, "Ch0 Dispatch TCP FIFO parity error" }, + { F_DISPIPFIFO0, "Ch0 Dispatch IP FIFO parity error" }, + { F_DISPETHFIFO0, "Ch0 Dispatch ETH FIFO parity error" }, + { F_DISPGREFIFO0, "Ch0 Dispatch GRE FIFO parity error" }, + { F_DISPCPL5FIFO0, "Ch0 Dispatch CPL5 FIFO parity error" }, + { 0 } + }; static const struct intr_info tp_e_eg_perr_cause = { .name = "TP_E_EG_PERR_CAUSE", .cause_reg = A_TP_E_EG_PERR_CAUSE, .enable_reg = A_TP_E_EG_PERR_ENABLE, .fatal = 0xffffffff, .flags = IHF_FATAL_IFF_ENABLED, - .details = NULL, + .details = tp_e_eg_perr_details, .actions = NULL, }; + static const struct intr_details tp_e_in0_perr_details[] = { + { F_DMXISSFIFO, "Demux ISS FIFO parity error" }, + { F_DMXERRFIFO, "Demux Error FIFO parity error" }, + { F_DMXATTFIFO, "Demux Attributes FIFO parity error" }, + { F_DMXTCPFIFO, "Demux TCP Fields FIFO parity error" }, + { F_DMXMPAFIFO, "Demux MPA FIFO parity error" }, + { F_DMXOPTFIFO, "Demux TCP Options FIFO parity error" }, + { F_INGTOKENFIFO, "Demux Ingress Token FIFO parity error" }, + { F_DMXPLDCHKOVFL1, "Ch1 PLD TxCheck FIFO Overflow" }, + { F_DMXPLDCHKFIFO1, "Ch1 PLD TxCheck FIFO parity error" }, + { F_DMXOPTFIFO1, "Ch1 Options buffer parity error" }, + { F_DMXMPAFIFO1, "Ch1 MPA FIFO parity error" }, + { F_DMXDBFIFO1, "Ch1 DB FIFO parity error" }, + { F_DMXATTFIFO1, "Ch1 Attribute FIFO parity error" }, + { F_DMXISSFIFO1, "Ch1 ISS FIFO parity error" }, + { F_DMXTCPFIFO1, "Ch1 TCP Fields FIFO parity error" }, + { F_DMXERRFIFO1, "Ch1 Error FIFO parity error" }, + { F_MPS2TPINTF1, "Ch1 MPS2TP Interface parity error" }, + { F_DMXPLDCHKOVFL0, "Ch0 PLD TxCheck FIFO Overflow" }, + { F_DMXPLDCHKFIFO0, "Ch0 PLD TxCheck FIFO parity error" }, + { F_DMXOPTFIFO0, "Ch0 Options buffer parity error" }, + { F_DMXMPAFIFO0, "Ch0 MPA FIFO parity error" }, + { F_DMXDBFIFO0, "Ch0 DB FIFO parity error" }, + { F_DMXATTFIFO0, "Ch0 Attribute FIFO parity error" }, + { F_DMXISSFIFO0, "Ch0 ISS FIFO parity error" }, + { F_DMXTCPFIFO0, "Ch0 TCP Fields FIFO parity error" }, + { F_DMXERRFIFO0, "Ch0 Error FIFO parity error" }, + { F_MPS2TPINTF0, "Ch0 MPS2TP Interface parity error" }, + { 0 } + }; static const struct intr_info tp_e_in0_perr_cause = { .name = "TP_E_IN0_PERR_CAUSE", .cause_reg = A_TP_E_IN0_PERR_CAUSE, .enable_reg = A_TP_E_IN0_PERR_ENABLE, .fatal = 0xffffffff, .flags = IHF_FATAL_IFF_ENABLED, - .details = NULL, + .details = tp_e_in0_perr_details, .actions = NULL, }; + static const struct intr_details tp_e_in1_perr_details[] = { + { F_DMXPLDCHKOVFL3, "Ch3 PLD TxCheck FIFO Overflow" }, + { F_DMXPLDCHKFIFO3, "Ch3 PLD TxCheck FIFO parity error" }, + { F_DMXOPTFIFO3, "Ch3 Options buffer parity error" }, + { F_DMXMPAFIFO3, "Ch3 MPA FIFO parity error" }, + { F_DMXDBFIFO3, "Ch3 DB FIFO parity error" }, + { F_DMXATTFIFO3, "Ch3 Attribute FIFO parity error" }, + { F_DMXISSFIFO3, "Ch3 ISS FIFO parity error" }, + { F_DMXTCPFIFO3, "Ch3 TCP Fields FIFO parity error" }, + { F_DMXERRFIFO3, "Ch3 Error FIFO parity error" }, + { F_MPS2TPINTF3, "Ch3 MPS2TP Interface parity error" }, + { F_DMXPLDCHKOVFL2, "Ch2 PLD TxCheck FIFO Overflow" }, + { F_DMXPLDCHKFIFO2, "Ch2 PLD TxCheck FIFO parity error" }, + { F_DMXOPTFIFO2, "Ch2 Options buffer parity error" }, + { F_DMXMPAFIFO2, "Ch2 MPA FIFO parity error" }, + { F_DMXDBFIFO2, "Ch2 DB FIFO parity error" }, + { F_DMXATTFIFO2, "Ch2 Attribute FIFO parity error" }, + { F_DMXISSFIFO2, "Ch2 ISS FIFO parity error" }, + { F_DMXTCPFIFO2, "Ch2 TCP Fields FIFO parity error" }, + { F_DMXERRFIFO2, "Ch2 Error FIFO parity error" }, + { F_MPS2TPINTF2, "Ch2 MPS2TP Interface parity error" }, + { 0 } + }; static const struct intr_info tp_e_in1_perr_cause = { .name = "TP_E_IN1_PERR_CAUSE", .cause_reg = A_TP_E_IN1_PERR_CAUSE, .enable_reg = A_TP_E_IN1_PERR_ENABLE, .fatal = 0xffffffff, .flags = IHF_FATAL_IFF_ENABLED, - .details = NULL, + .details = tp_e_in1_perr_details, .actions = NULL, }; + static const struct intr_details tp_other_perr_details[] = { + { F_DMARBTPERR, "DMARBT MA Rsp Interface parity Error" }, + { F_MMGRCACHEDATASRAM, "TP MMGR Cache Data SRAM" }, + { F_MMGRCACHETAGFIFO, "TP MMGR Cache Tag FIFO" }, + { F_DBL2TLUTPERR, "TP DB Lookup Table" }, + { F_DBTXTIDPERR, "TP DB FIFOs" }, + { F_DBEXTPERR, "TP DB Extended Opcode FIFO" }, + { F_DBOPPERR, "TP DB Opcode FIFO" }, + { F_TMCACHEPERR, "TP TM Cache SRAM" }, + { F_TPPROTOSRAM, "TP Protocol SRAM" }, + { F_HSPSRAM, "HighSpeed SRAM" }, + { F_RATEGRPSRAM, "Rate Group SRAM" }, + { F_TXFBSEQFIFO, "Tx Feedback Sequence Number FIFO" }, + { F_CMDATASRAM, "Cache Data SRAM" }, + { F_CMTAGFIFO, "Cache Tag FIFO" }, + { F_RFCOPFIFO, "RCF Opcode FIFO" }, + { F_DELINVFIFO, "Delete Invalid FIFO" }, + { F_RSSCFGSRAM, "RSS Config or Round-Robin SRAM" }, + { F_RSSKEYSRAM, "RSS Key SRAM" }, + { F_RSSLKPSRAM, "RSS Lookup SRAM" }, + { F_SRQSRAM, "SRQ SRAM" }, + { F_ARPDASRAM, "ARP DA SRAM" }, + { F_ARPSASRAM, "ARP SA SRAM" }, + { F_ARPGRESRAM, "ARP GRE SRAM" }, + { F_ARPIPSECSRAM1, "ARP IPSec SRAM0" }, + { F_ARPIPSECSRAM0, "ARP IPSec SRAM1" }, + { 0 } + }; static const struct intr_info tp_o_perr_cause = { .name = "TP_O_PERR_CAUSE", .cause_reg = A_TP_O_PERR_CAUSE, .enable_reg = A_TP_O_PERR_ENABLE, .fatal = 0xffffffff, .flags = IHF_FATAL_IFF_ENABLED, - .details = NULL, + .details = tp_other_perr_details, .actions = NULL, }; bool fatal; - fatal = t4_handle_intr(adap, &tp_intr_info, 0, flags); if (chip_id(adap) > CHELSIO_T6) { - fatal |= t4_handle_intr(adap, &tp_inic_perr_cause, 0, flags); + tp_intr_info.details = t7_tp_intr_details; + fatal = t4_handle_intr(adap, &tp_intr_info, 0, flags); + fatal |= t4_handle_intr(adap, &tp_cerr_cause, 0, flags); fatal |= t4_handle_intr(adap, &tp_c_perr_cause, 0, flags); fatal |= t4_handle_intr(adap, &tp_e_eg_perr_cause, 0, flags); fatal |= t4_handle_intr(adap, &tp_e_in0_perr_cause, 0, flags); fatal |= t4_handle_intr(adap, &tp_e_in1_perr_cause, 0, flags); fatal |= t4_handle_intr(adap, &tp_o_perr_cause, 0, flags); + } else { + tp_intr_info.details = tp_intr_details; + fatal = t4_handle_intr(adap, &tp_intr_info, 0, flags); } + clear_int_cause_reg(adap, &tp_intr_info, flags); return (fatal); } @@ -5133,16 +5362,86 @@ static bool tp_intr_handler(struct adapter *adap, int arg, int flags) */ static bool sge_intr_handler(struct adapter *adap, int arg, int flags) { + static const struct intr_details sge_int1_details[] = { + { F_PERR_FLM_CREDITFIFO, "SGE FLM credit FIFO parity error" }, + { F_PERR_IMSG_HINT_FIFO, "SGE IMSG hint FIFO parity error" }, + { F_PERR_HEADERSPLIT_FIFO3 | F_PERR_HEADERSPLIT_FIFO2, + "SGE header split FIFO parity error" }, + { F_PERR_PAYLOAD_FIFO3 | F_PERR_PAYLOAD_FIFO2, + "SGE payload FIFO parity error" }, + { F_PERR_PC_RSP, "SGE PC response parity error" }, + { F_PERR_PC_REQ, "SGE PC request parity error" }, + { 0x003c0000, "SGE DBP PC response FIFO parity error" }, + { F_PERR_DMARBT, "SGE DMA RBT parity error" }, + { F_PERR_FLM_DBPFIFO, "SGE FLM DBP FIFO parity error" }, + { F_PERR_FLM_MCREQ_FIFO, "SGE FLM MC request FIFO parity error" }, + { F_PERR_FLM_HINTFIFO, "SGE FLM hint FIFO parity error" }, + { 0x00003c00, "SGE align control FIFO parity error" }, + { 0x000003c0, "SGE EDMA FIFO parity error" }, + { 0x0000003c, "SGE PD FIFO parity error" }, + { F_PERR_ING_CTXT_MIFRSP, "SGE Ingress context MIF response parity error" }, + { F_PERR_EGR_CTXT_MIFRSP, "SGE Egress context MIF response parity error" }, + { 0 } + }; static const struct intr_info sge_int1_info = { .name = "SGE_INT_CAUSE1", .cause_reg = A_SGE_INT_CAUSE1, .enable_reg = A_SGE_INT_ENABLE1, .fatal = 0xffffffff, .flags = IHF_FATAL_IFF_ENABLED, - .details = NULL, + .details = sge_int1_details, .actions = NULL, }; - static const struct intr_info sge_int2_info = { + static const struct intr_details t7_sge_int2_details[] = { + { F_TF_FIFO_PERR, "SGE TF FIFO parity error" }, + { F_PERR_EGR_DBP_TX_COAL, "SGE egress DBP TX coal parity error" }, + { F_PERR_DBP_FL_FIFO, "SGE DBP FL FIFO parity error" }, + { F_DEQ_LL_PERR, "SGE linked list SRAM parity error" }, + { F_ENQ_PERR, "SGE enq tag SRAM parity error" }, + { F_DEQ_OUT_PERR, "SGE tbuf deq output FIFO parity error" }, + { F_BUF_PERR, "SGE tbuf main buffer parity error" }, + { F_PERR_CONM_SRAM, "SGE CONM SRAM parity error" }, + { F_PERR_ISW_IDMA3_FIFO | F_PERR_ISW_IDMA2_FIFO | + F_PERR_ISW_IDMA1_FIFO | F_PERR_ISW_IDMA0_FIFO, + "SGE ISW IDMA FIFO parity error" }, + { F_PERR_ISW_DBP_FIFO, "SGE ISW DBP FIFO parity error" }, + { F_PERR_ISW_GTS_FIFO, "SGE ISW GTS FIFO parity error" }, + { F_PERR_ITP_EVR, "SGE ITP EVR parity error" }, + { F_PERR_FLM_CNTXMEM, "SGE FLM context memory parity error" }, + { F_PERR_FLM_L1CACHE, "SGE FLM L1 cache parity error" }, + { F_SGE_IPP_FIFO_PERR, "SGE IPP FIFO parity error" }, + { F_PERR_DBP_HP_FIFO, "SGE DBP HP FIFO parity error" }, + { F_PERR_DB_FIFO, "SGE doorbell FIFO parity error" }, + { F_PERR_ING_CTXT_CACHE | F_PERR_EGR_CTXT_CACHE, + "SGE context cache parity error" }, + { F_PERR_BASE_SIZE, "SGE base size parity error" }, + { 0 } + }; + static const struct intr_details t6_sge_int2_details[] = { + { F_PERR_DBP_HINT_FL_FIFO, "SGE DBP hint FL FIFO parity error" }, + { F_PERR_EGR_DBP_TX_COAL, "SGE egress DBP TX coal parity error" }, + { F_PERR_DBP_FL_FIFO, "SGE DBP FL FIFO parity error" }, + { F_DEQ_LL_PERR, "SGE tbuf dequeue linked list SRAM parity error" }, + { F_ENQ_PERR, "SGE tbuf enqueue tag SRAM parity error" }, + { F_DEQ_OUT_PERR, "SGE tbuf dequeue output FIFO parity error" }, + { F_BUF_PERR, "SGE tbuf main buffer parity error" }, + { F_PERR_CONM_SRAM, "SGE CONM SRAM parity error" }, + { F_PERR_ISW_IDMA1_FIFO, "SGE ISW IDMA FIFO parity error" }, + { F_PERR_ISW_IDMA0_FIFO, "SGE ISW IDMA FIFO parity error" }, + { F_PERR_ISW_DBP_FIFO, "SGE ISW DBP FIFO parity error" }, + { F_PERR_ISW_GTS_FIFO, "SGE ISW GTS FIFO parity error" }, + { F_PERR_ITP_EVR, "SGE ITP EVR parity error" }, + { F_PERR_FLM_CNTXMEM, "SGE FLM context memory parity error" }, + { F_PERR_FLM_L1CACHE, "SGE FLM L1 cache parity error" }, + { F_PERR_DBP_HINT_FIFO, "SGE DBP hint FIFO parity error" }, + { F_PERR_DBP_HP_FIFO, "SGE DBP high priority FIFO parity error" }, + { F_PERR_DB_FIFO, "SGE DBP merge DB FIFO parity error" }, + { F_PERR_ING_CTXT_CACHE, "SGE ingress context cache parity error" }, + { F_PERR_EGR_CTXT_CACHE, "SGE egress context cache parity error" }, + { F_PERR_BASE_SIZE, "SGE base size parity error" }, + { 0 } + }; + struct intr_info sge_int2_info = { .name = "SGE_INT_CAUSE2", .cause_reg = A_SGE_INT_CAUSE2, .enable_reg = A_SGE_INT_ENABLE2, @@ -5231,16 +5530,105 @@ static bool sge_intr_handler(struct adapter *adap, int arg, int flags) .details = NULL, .actions = NULL, }; + static const struct intr_details sge_int4_details[] = { + { F_ERR_ISHIFT_UR1 | F_ERR_ISHIFT_UR0, "SGE ishift underrun" }, + { F_BAR2_EGRESS_LEN_OR_ADDR_ERR, "SGE BAR2 PL access length or alignment error" }, + { F_ERR_CPL_EXCEED_MAX_IQE_SIZE1 | F_ERR_CPL_EXCEED_MAX_IQE_SIZE0, + "SGE CPL exceeds max IQE size" }, + { F_ERR_WR_LEN_TOO_LARGE3 | F_ERR_WR_LEN_TOO_LARGE2 | + F_ERR_WR_LEN_TOO_LARGE1 | F_ERR_WR_LEN_TOO_LARGE0, + "SGE WR length too large" }, + { F_ERR_LARGE_MINFETCH_WITH_TXCOAL3 | F_ERR_LARGE_MINFETCH_WITH_TXCOAL2 | + F_ERR_LARGE_MINFETCH_WITH_TXCOAL1 | F_ERR_LARGE_MINFETCH_WITH_TXCOAL0, + "SGE invalid MinFetchBurst with TxCoalesce" }, + { F_COAL_WITH_HP_DISABLE_ERR, "SGE coalesce with HP disable error" }, + { F_BAR2_EGRESS_COAL0_ERR, "SGE BAR2 PL access addr offset 0" }, + { F_BAR2_EGRESS_SIZE_ERR, "SGE BAR2 illegal egress QID access" }, + { F_FLM_PC_RSP_ERR, "SGE FLM PC response error" }, + { F_ERR_TH3_MAX_FETCH | F_ERR_TH2_MAX_FETCH | + F_ERR_TH1_MAX_FETCH | F_ERR_TH0_MAX_FETCH, + "SGE max fetch violation" }, + { F_ERR_RX_CPL_PACKET_SIZE1 | F_ERR_RX_CPL_PACKET_SIZE0, + "SGE CPL length mismatch error" }, + { F_ERR_BAD_UPFL_INC_CREDIT3 | F_ERR_BAD_UPFL_INC_CREDIT2 | + F_ERR_BAD_UPFL_INC_CREDIT1 | F_ERR_BAD_UPFL_INC_CREDIT0, + "SGE upfl credit wrap error" }, + { F_ERR_PHYSADDR_LEN0_IDMA1 | F_ERR_PHYSADDR_LEN0_IDMA0, + "SGE CPL_RX_PHYS_ADDR length 0 error" }, + { F_ERR_FLM_INVALID_PKT_DROP1 | F_ERR_FLM_INVALID_PKT_DROP0, + "SGE IDMA packet drop due to invalid FLM context" }, + { F_ERR_UNEXPECTED_TIMER, "SGE unexpected timer error" }, + { 0 } + }; static const struct intr_info sge_int4_info = { .name = "SGE_INT_CAUSE4", .cause_reg = A_SGE_INT_CAUSE4, .enable_reg = A_SGE_INT_ENABLE4, .fatal = 0, .flags = 0, - .details = NULL, + .details = sge_int4_details, .actions = NULL, }; - static const struct intr_info sge_int5_info = { + static const struct intr_details t7_sge_int5_details[] = { + { F_ERR_T_RXCRC, "SGE RxCRC error" }, + { F_PERR_MC_RSPDATA, "SGE MC response data parity error" }, + { F_PERR_PC_RSPDATA, "SGE PC response data parity error" }, + { F_PERR_PD_RDRSPDATA, "SGE PD read response data parity error" }, + { F_PERR_U_RXDATA, "SGE U Rx data parity error" }, + { F_PERR_UD_RXDATA, "SGE UD Rx data parity error" }, + { F_PERR_UP_DATA, "SGE uP data parity error" }, + { F_PERR_CIM2SGE_RXDATA, "SGE CIM2SGE Rx data parity error" }, + { F_PERR_IMSG_PD_FIFO, "SGE IMSG PD FIFO parity error" }, + { F_PERR_ULPTX_FIFO1 | F_PERR_ULPTX_FIFO0, "SGE ULPTX FIFO parity error" }, + { F_PERR_IDMA2IMSG_FIFO3 | F_PERR_IDMA2IMSG_FIFO2 | + F_PERR_IDMA2IMSG_FIFO1 | F_PERR_IDMA2IMSG_FIFO0, + "SGE IDMA2IMSG FIFO parity error" }, + { F_PERR_POINTER_DATA_FIFO3 | F_PERR_POINTER_DATA_FIFO2 | + F_PERR_POINTER_DATA_FIFO1 | F_PERR_POINTER_DATA_FIFO0, + "SGE pointer data FIFO parity error" }, + { F_PERR_POINTER_HDR_FIFO3 | F_PERR_POINTER_HDR_FIFO2 | + F_PERR_POINTER_HDR_FIFO1 | F_PERR_POINTER_HDR_FIFO0, + "SGE pointer header FIFO parity error" }, + { F_PERR_PAYLOAD_FIFO1 | F_PERR_PAYLOAD_FIFO0, + "SGE payload FIFO parity error" }, + { F_PERR_MGT_BAR2_FIFO, "SGE MGT BAR2 FIFO parity error" }, + { F_PERR_HEADERSPLIT_FIFO1 | F_PERR_HEADERSPLIT_FIFO0, + "SGE header split FIFO parity error" }, + { F_PERR_HINT_DELAY_FIFO, "SGE hint delay FIFO parity error" }, + { 0 } + }; + static const struct intr_details t6_sge_int5_details[] = { + { F_ERR_T_RXCRC, "SGE T RxCRC parity error" }, + { F_PERR_MC_RSPDATA, "SGE MC response data parity error" }, + { F_PERR_PC_RSPDATA, "SGE PC response data parity error" }, + { F_PERR_U_RXDATA | F_PERR_UD_RXDATA, "SGE ULP Rx data parity error" }, + { F_PERR_UP_DATA, "SGE uP data parity error" }, + { F_PERR_CIM2SGE_RXDATA, "SGE CIM2SGE Rx data parity error" }, + { F_PERR_HINT_DELAY_FIFO1 | F_PERR_HINT_DELAY_FIFO0, + "SGE hint delay FIFO parity error" }, + { F_PERR_IMSG_PD_FIFO, "SGE IMSG PD FIFO parity error" }, + { F_PERR_ULPTX_FIFO1 | F_PERR_ULPTX_FIFO0, + "SGE ULPTX FIFO parity error" }, + { F_PERR_IDMA2IMSG_FIFO1 | F_PERR_IDMA2IMSG_FIFO0, + "SGE IDMA2IMSG FIFO parity error" }, + { F_PERR_POINTER_DATA_FIFO1 | F_PERR_POINTER_DATA_FIFO0, + "SGE pointer data FIFO parity error" }, + { F_PERR_POINTER_HDR_FIFO1 | F_PERR_POINTER_HDR_FIFO0, + "SGE pointer header FIFO parity error" }, + { F_PERR_PAYLOAD_FIFO1 | F_PERR_PAYLOAD_FIFO0, + "SGE payload FIFO parity error" }, + { F_PERR_EDMA_INPUT_FIFO3 | F_PERR_EDMA_INPUT_FIFO2 | + F_PERR_EDMA_INPUT_FIFO1 | F_PERR_EDMA_INPUT_FIFO0, + "SGE EDMA input FIFO parity error" }, + { F_PERR_MGT_BAR2_FIFO, "SGE MGT BAR2 FIFO parity error" }, + { F_PERR_HEADERSPLIT_FIFO1 | F_PERR_HEADERSPLIT_FIFO0, + "SGE header split FIFO parity error" }, + { F_PERR_CIM_FIFO1 | F_PERR_CIM_FIFO0, "SGE CIM FIFO parity error" }, + { F_PERR_IDMA_SWITCH_OUTPUT_FIFO1 | F_PERR_IDMA_SWITCH_OUTPUT_FIFO0, + "SGE IDMA switch output FIFO parity error" }, + { 0 } + }; + struct intr_info sge_int5_info = { .name = "SGE_INT_CAUSE5", .cause_reg = A_SGE_INT_CAUSE5, .enable_reg = A_SGE_INT_ENABLE5, @@ -5249,31 +5637,94 @@ static bool sge_intr_handler(struct adapter *adap, int arg, int flags) .details = NULL, .actions = NULL, }; + static const struct intr_details sge_int6_details[] = { + /* T7+ */ + { 0xe0000000, "SGE fatal DEQ0 DRDY error" }, + { 0x1c000000, "SGE fatal OUT0 DRDY error" }, + { F_IMSG_DBG3_STUCK | F_IMSG_DBG2_STUCK | + F_IMSG_DBG1_STUCK | F_IMSG_DBG0_STUCK, + "SGE IMSG stuck due to insufficient credits" }, + /* T6 + */ + { F_ERR_DB_SYNC, "SGE doorbell sync failed" }, + { F_ERR_GTS_SYNC, "SGE GTS sync failed" }, + { F_FATAL_LARGE_COAL, "SGE BAR2 payload too large" }, + { F_PL_BAR2_FRM_ERR, "SGE BAR2 framing error" }, + { F_SILENT_DROP_TX_COAL, "SGE silent drop of Tx coal WR" }, + { F_ERR_INV_CTXT4, "SGE context access for invalid queue thread 4" }, + { F_ERR_BAD_DB_PIDX4, "SGE doorbell pidx too large thread 4" }, + { F_ERR_BAD_UPFL_INC_CREDIT4, "SGE upfl credit wrap thread 4" }, + { F_FATAL_TAG_MISMATCH, "SGE doorbell tag mismatch" }, + { F_FATAL_ENQ_CTL_RDY, "SGE enq_ctl_fifo overflow" }, + { F_ERR_PC_RSP_LEN3 | F_ERR_PC_RSP_LEN2 | + F_ERR_PC_RSP_LEN1 | F_ERR_PC_RSP_LEN0, + "SGE PCIe response error for DBP threads" }, + { F_FATAL_ENQ2LL_VLD, "SGE tbuf fatal_enq2ll_vld" }, + { F_FATAL_LL_EMPTY, "SGE tbuf fatal_ll_empty" }, + { F_FATAL_OFF_WDENQ, "SGE tbuf fatal_off_wdenq" }, + { 0x00000018, "SGE tbuf fatal_deq1_drdy" }, + { 0x00000006, "SGE tbuf fatal_out1_drdy" }, + { F_FATAL_DEQ, "SGE tbuf fatal_deq" }, + { 0 } + }; static const struct intr_info sge_int6_info = { .name = "SGE_INT_CAUSE6", .cause_reg = A_SGE_INT_CAUSE6, .enable_reg = A_SGE_INT_ENABLE6, .fatal = 0, .flags = 0, - .details = NULL, + .details = sge_int6_details, .actions = NULL, }; + static const struct intr_details sge_int7_details[] = { + { F_HINT_FIFO_FULL, "SGE hint FIFO full" }, + { F_CERR_HINT_DELAY_FIFO, "SGE hint delay FIFO ECC error" }, + { F_COAL_TIMER_FIFO_PERR, "SGE coalescing timer FIFO parity error" }, + { F_CMP_FIFO_PERR, "SGE CMP FIFO parity error" }, + { F_SGE_IPP_FIFO_CERR, "SGE IPP FIFO ECC error" }, + { F_CERR_ING_CTXT_CACHE | F_CERR_EGR_CTXT_CACHE, + "SGE context cache ECC error" }, + { F_IMSG_CNTX_PERR, "SGE IMSG context parity error" }, + { F_PD_FIFO_PERR, "SGE PD FIFO parity error" }, + { F_IMSG_512_FIFO_PERR, "SGE IMSG 512 FIFO parity error" }, + { F_CPLSW_FIFO_PERR, "SGE CPLSW FIFO parity error" }, + { F_IMSG_FIFO_PERR, "SGE IMSG FIFO parity error" }, + { F_CERR_ITP_EVR, "SGE ITP EVR ECC error" }, + { F_CERR_CONM_SRAM, "SGE CONM SRAM ECC error" }, + { F_CERR_FLM_CNTXMEM, "SGE FLM context memory ECC error" }, + { F_CERR_FUNC_QBASE, "SGE function queue base ECC error" }, + { F_IMSG_CNTX_CERR, "SGE IMSG context ECC error" }, + { F_PD_FIFO_CERR, "SGE PD FIFO ECC error" }, + { F_IMSG_512_FIFO_CERR, "SGE IMSG 512 FIFO ECC error" }, + { F_CPLSW_FIFO_CERR, "SGE CPLSW FIFO ECC error" }, + { F_IMSG_FIFO_CERR, "SGE IMSG FIFO ECC error" }, + { 0x0000001e, "SGE header split FIFO ECC error" }, // Bits 4:1 + { F_CERR_FLM_L1CACHE, "SGE FLM L1 cache ECC error" }, + { 0 } + }; static const struct intr_info sge_int7_info = { .name = "SGE_INT_CAUSE7", .cause_reg = A_SGE_INT_CAUSE7, .enable_reg = A_SGE_INT_ENABLE7, .fatal = 0, .flags = 0, - .details = NULL, + .details = sge_int7_details, .actions = NULL, }; + static const struct intr_details sge_int8_details[] = { + { F_TRACE_RXPERR, "SGE trace packet parity error" }, + { F_U3_RXPERR | F_U2_RXPERR | F_U1_RXPERR | F_U0_RXPERR, + "SGE ULP interface parity error" }, + { F_T3_RXPERR | F_T2_RXPERR | F_T1_RXPERR | F_T0_RXPERR, + "SGE TP interface parity error" }, + { 0 } + }; static const struct intr_info sge_int8_info = { .name = "SGE_INT_CAUSE8", .cause_reg = A_SGE_INT_CAUSE8, .enable_reg = A_SGE_INT_ENABLE8, .fatal = 0, .flags = 0, - .details = NULL, + .details = sge_int8_details, .actions = NULL, }; bool fatal; @@ -5281,8 +5732,14 @@ static bool sge_intr_handler(struct adapter *adap, int arg, int flags) if (chip_id(adap) <= CHELSIO_T5) { sge_int3_info.details = sge_int3_details; + } else if (chip_id(adap) == CHELSIO_T6) { + sge_int3_info.details = t6_sge_int3_details; + sge_int2_info.details = t6_sge_int2_details; + sge_int5_info.details = t6_sge_int5_details; } else { sge_int3_info.details = t6_sge_int3_details; + sge_int2_info.details = t7_sge_int2_details; + sge_int5_info.details = t7_sge_int5_details; } fatal = false; @@ -5316,6 +5773,19 @@ static bool sge_intr_handler(struct adapter *adap, int arg, int flags) */ static bool cim_intr_handler(struct adapter *adap, int arg, int flags) { + static const struct intr_details cim_host_t7_intr_details[] = { + { F_CORE7ACCINT, "CIM slave core 7 access interrupt "}, + { F_CORE6ACCINT, "CIM slave core 6 access interrupt "}, + { F_CORE5ACCINT, "CIM slave core 5 access interrupt "}, + { F_CORE4ACCINT, "CIM slave core 4 access interrupt "}, + { F_CORE3ACCINT, "CIM slave core 3 access interrupt "}, + { F_CORE2ACCINT, "CIM slave core 2 access interrupt "}, + { F_CORE1ACCINT, "CIM slave core 1 access interrupt "}, + { F_TIMER1INT, "CIM TIMER0 interrupt" }, + { F_TIMER0INT, "CIM TIMER0 interrupt" }, + { F_PREFDROPINT, "CIM control register prefetch drop" }, + { 0} + }; static const struct intr_details cim_host_intr_details[] = { /* T6+ */ { F_PCIE2CIMINTFPARERR, "CIM IBQ PCIe interface parity error" }, @@ -5328,8 +5798,8 @@ static bool cim_intr_handler(struct adapter *adap, int arg, int flags) { F_SGE2CIMINTFPARERR, "CIM IBQ SGE interface parity error" }, { F_ULP2CIMINTFPARERR, "CIM IBQ ULP_TX interface parity error" }, { F_TP2CIMINTFPARERR, "CIM IBQ TP interface parity error" }, - { F_OBQSGERX1PARERR, "CIM OBQ SGE1_RX parity error" }, - { F_OBQSGERX0PARERR, "CIM OBQ SGE0_RX parity error" }, + { F_OBQSGERX1PARERR, "CIM OBQ PCIE_RX parity error" }, + { F_OBQSGERX0PARERR, "CIM OBQ SGE_RX parity error" }, /* T4+ */ { F_TIEQOUTPARERRINT, "CIM TIEQ outgoing FIFO parity error" }, @@ -5354,16 +5824,17 @@ static bool cim_intr_handler(struct adapter *adap, int arg, int flags) { F_PREFDROPINT, "CIM control register prefetch drop" }, { 0} }; - static const struct intr_info cim_host_intr_info = { + struct intr_info cim_host_intr_info = { .name = "CIM_HOST_INT_CAUSE", .cause_reg = A_CIM_HOST_INT_CAUSE, .enable_reg = A_CIM_HOST_INT_ENABLE, .fatal = 0x007fffe6, .flags = IHF_FATAL_IFF_ENABLED, - .details = cim_host_intr_details, + .details = NULL, .actions = NULL, }; static const struct intr_details cim_host_upacc_intr_details[] = { + { F_CONWRERRINT, "CIM condition write error "}, { F_EEPROMWRINT, "CIM EEPROM came out of busy state" }, { F_TIMEOUTMAINT, "CIM PIF MA timeout" }, { F_TIMEOUTINT, "CIM PIF timeout" }, @@ -5423,18 +5894,54 @@ static bool cim_intr_handler(struct adapter *adap, int arg, int flags) .details = NULL, .actions = NULL, }; + static const struct intr_details cim_perr_cause_details[] = { + { F_T7_MA_CIM_INTFPERR, "MA2CIM interface parity error" }, + { F_T7_MBHOSTPARERR, "Mailbox Host Read parity error" }, + { F_MAARBINVRSPTAG, "MA Arbiter Invalid Response Tag (Fatal)" }, + { F_MAARBFIFOPARERR, "MA Arbiter FIFO Parity Error" }, + { F_SEMSRAMPARERR, "Semaphore logic SRAM Parity Error" }, + { F_RSACPARERR, "RSA Code SRAM Parity Error" }, + { F_RSADPARERR, "RSA Data SRAM Parity Error" }, + { F_T7_PLCIM_MSTRSPDATAPARERR, "PL2CIM Master response data parity error" }, + { F_T7_PCIE2CIMINTFPARERR, "IBQ PCIE intf parity error" }, + { F_T7_NCSI2CIMINTFPARERR, "IBQ NCSI intf parity error" }, + { F_T7_SGE2CIMINTFPARERR, "IBQ SGE Intf Parity error" }, + { F_T7_ULP2CIMINTFPARERR, "IBQ ULP_TX intf parity error" }, + { F_T7_TP2CIMINTFPARERR, "IBQ TP intf parity error" }, + { F_CORE7PARERR, "Slave Core7 parity error" }, + { F_CORE6PARERR, "Slave Core6 parity error" }, + { F_CORE5PARERR, "Slave Core5 parity error" }, + { F_CORE4PARERR, "Slave Core4 parity error" }, + { F_CORE3PARERR, "Slave Core3 parity error" }, + { F_CORE2PARERR, "Slave Core2 parity error" }, + { F_CORE1PARERR, "Slave Core1 parity error" }, + { F_GFTPARERR, "GFT block Memory parity error" }, + { F_MPSRSPDATAPARERR, "MPS lookup interface Response parity error" }, + { F_ER_RSPDATAPARERR, "Expansion ROM/Flash Interface Response Parity Error" }, + { F_FLOWFIFOPARERR, "SGE FlowID Prefetch FIFO Parity Error" }, + { F_OBQSRAMPARERR, "OBQ SRAM Parity Error" }, + { F_TIEQOUTPARERR, "TIE Queue Outgoing FIFO parity error" }, + { F_TIEQINPARERR, "TIE Queue Incoming FIFO parity error" }, + { F_PIFRSPPARERR, "PIF Response interface FIFO Parity error" }, + { F_PIFREQPARERR, "PIF Request interface FIFO Parity error" }, + { 0 } + }; static const struct intr_info cim_perr_cause = { .name = "CIM_PERR_CAUSE", .cause_reg = A_CIM_PERR_CAUSE, .enable_reg = A_CIM_PERR_ENABLE, .fatal = 0xffffffff, .flags = IHF_FATAL_IFF_ENABLED, - .details = NULL, + .details = cim_perr_cause_details, .actions = NULL, }; u32 val, fw_err; bool fatal; + if (chip_id(adap) >= CHELSIO_T7) + cim_host_intr_info.details = cim_host_t7_intr_details; + else + cim_host_intr_info.details = cim_host_intr_details; /* * When the Firmware detects an internal error which normally wouldn't * raise a Host Interrupt, it forces a CIM Timer0 interrupt in order @@ -5477,62 +5984,237 @@ static bool ulprx_intr_handler(struct adapter *adap, int arg, int flags) { 0x007fffff, "ULPRX parity error" }, { 0 } }; - static const struct intr_info ulprx_intr_info = { + static const struct intr_details t6_ulprx_int_cause_details[] = { + { F_SE_CNT_MISMATCH_1, "SE count mismatch in channel1" }, + { F_SE_CNT_MISMATCH_0, "SE count mismatch in channel 0" }, + { F_CAUSE_CTX_1, "Context access error on channel 1" }, + { F_CAUSE_CTX_0, "Context access error on channel 0" }, + { F_CAUSE_FF, "filp-flop based fifos" }, + { F_CAUSE_APF_1, "Arb prefetch memory, channel 1" }, + { F_CAUSE_APF_0, "Arb prefetch memory, channel 0" }, + { F_CAUSE_AF_1, "Arb fetch memory, channel 1" }, + { F_CAUSE_AF_0, "Arb fetch memory, channel 0" }, + { F_CAUSE_DDPDF_1, "ddp_data_fifo Fifo, channel 1" }, + { F_CAUSE_DDPMF_1, "ddp_msg_fifo Fifo, channel 1" }, + { F_CAUSE_MEMRF_1, "mem_req_fifo_d Fifo, channel 1" }, + { F_CAUSE_PRSDF_1, "prsr_data_fifo Fifo, channel 1" }, + { F_CAUSE_DDPDF_0, "ddp_data_fifo Fifo, channel 0" }, + { F_CAUSE_DDPMF_0, "ddp_msg_fifo Fifo, channel 0" }, + { F_CAUSE_MEMRF_0, "mem_req_fifo_d Fifo, channel 0" }, + { F_CAUSE_PRSDF_0, "prsr_data_fifo Fifo, channel 0" }, + { F_CAUSE_PCMDF_1, "Pcmd Fifo, channel 1" }, + { F_CAUSE_TPTCF_1, "tpt_ctl_fifo Fifo, channel 1" }, + { F_CAUSE_DDPCF_1, "ddp_ctl_fifo Fifo, channel 1" }, + { F_CAUSE_MPARF_1, "mpar_ctl_fifo Fifo, channel 1" }, + { F_CAUSE_MPARC_1, "mpac_ctl_fifo Fifo, channel 1" }, + { F_CAUSE_PCMDF_0, "Pcmd Fifo, channel 0" }, + { F_CAUSE_TPTCF_0, "tpt_ctl_fifo Fifo, channel 0" }, + { F_CAUSE_DDPCF_0, "ddp_ctl_fifo Fifo, channel 0" }, + { F_CAUSE_MPARF_0, "mpar_ctl_fifo Fifo, channel 0" }, + { F_CAUSE_MPARC_0, "mpac_ctl_fifo Fifo, channel 0" }, + { 0 } + }; + static const struct intr_details t7_ulprx_int_cause_details[] = { + { F_CERR_PCMD_FIFO_3, "PCMD FIFO correctable Error3" }, + { F_CERR_PCMD_FIFO_2, "PCMD FIFO correctable Error2" }, + { F_CERR_PCMD_FIFO_1, "PCMD FIFO correctable Error1" }, + { F_CERR_PCMD_FIFO_0, "PCMD FIFO correctable Error0" }, + { F_CERR_DATA_FIFO_3, "DDP Data FIFO correctable Error3" }, + { F_CERR_DATA_FIFO_2, "DDP Data FIFO correctable Error2" }, + { F_CERR_DATA_FIFO_1, "DDP Data FIFO correctable Error1" }, + { F_CERR_DATA_FIFO_0, "DDP Data FIFO correctable Error0" }, + { F_SE_CNT_MISMATCH_3, "SE count mismatch in channel3" }, + { F_SE_CNT_MISMATCH_2, "SE count mismatch in channel2" }, + { F_T7_SE_CNT_MISMATCH_1, "SE count mismatch in channel1" }, + { F_T7_SE_CNT_MISMATCH_0, "SE count mismatch in channel 0" }, + { F_T7_ENABLE_CTX_3, "Context access error on channel 3" }, + { F_T7_ENABLE_CTX_2, "Context access error on channel 2" }, + { F_T7_ENABLE_CTX_1, "Context access error on channel 1" }, + { F_T7_ENABLE_CTX_0, "Context access error on channel 0" }, + { F_T7_ENABLE_ALN_SDC_ERR_3, "SDC error reported by aligner in channel3" }, + { F_T7_ENABLE_ALN_SDC_ERR_2, "SDC error reported by aligner in channel2" }, + { F_T7_ENABLE_ALN_SDC_ERR_1, "SDC error reported by aligner in channel1" }, + { F_T7_ENABLE_ALN_SDC_ERR_0, "SDC error reported by aligner in channel0" }, + { 0 } + }; + struct intr_info ulprx_intr_info = { .name = "ULP_RX_INT_CAUSE", .cause_reg = A_ULP_RX_INT_CAUSE, .enable_reg = A_ULP_RX_INT_ENABLE, .fatal = 0x07ffffff, .flags = IHF_FATAL_IFF_ENABLED, - .details = ulprx_intr_details, + .details = NULL, .actions = NULL, }; + static const struct intr_details ulprx_int_cause_2_details[] = { + { F_ULPRX2MA_INTFPERR, "SDC error reported by ULPRX2MA interface parity checker" }, + { F_ALN_SDC_ERR_1, "SDC error reported by aligner in channel 1" }, + { F_ALN_SDC_ERR_0, "SDC error reported by aligner in channel 0" }, + { F_PF_UNTAGGED_TPT_1, "Parity error from Untagged TPT prefetch fifo channel 1" }, + { F_PF_UNTAGGED_TPT_0, "Parity error from Untagged TPT prefetch fifo channel 0" }, + { F_PF_PBL_1, "Parity error from PBL prefetch fifo channel 1" }, + { F_PF_PBL_0, "Parity error from PBL prefetch fifo channel 0" }, + { F_DDP_HINT_1, "DDP hint fifo Perr in channel 1" }, + { F_DDP_HINT_0, "DDP hint fifo Perr in channel 0" }, + { 0 } + }; static const struct intr_info ulprx_intr2_info = { .name = "ULP_RX_INT_CAUSE_2", .cause_reg = A_ULP_RX_INT_CAUSE_2, .enable_reg = A_ULP_RX_INT_ENABLE_2, .fatal = 0, .flags = 0, - .details = NULL, + .details = ulprx_int_cause_2_details, .actions = NULL, }; + static const struct intr_details ulprx_int_cause_pcmd_details[] = { + { F_CAUSE_PCMD_SFIFO_3, "Small FIFOs, channel 3" }, + { F_CAUSE_PCMD_FIFO_3, "pcmd_ctl_fifo, channel 3" }, + { F_CAUSE_PCMD_DDP_HINT_3, "ddp_hint_ctl_fifo FIFO, channel 3" }, + { F_CAUSE_PCMD_TPT_3, "tpt_ctl_fifo FIFO, channel 3" }, + { F_CAUSE_PCMD_DDP_3, "ddp_ctl_fifo FIFO, channel 3" }, + { F_CAUSE_PCMD_MPAR_3, "mpar_ctl_fifo FIFO, channel 3" }, + { F_CAUSE_PCMD_MPAC_3, "mpac_ctl_fifo FIFO, channel 3" }, + { F_CAUSE_PCMD_SFIFO_2, "Small FIFOs, channel 2" }, + { F_CAUSE_PCMD_FIFO_2, "pcmd_ctl_fifo, channel 2" }, + { F_CAUSE_PCMD_DDP_HINT_2, "ddp_hint_ctl_fifo FIFO, channel 2" }, + { F_CAUSE_PCMD_TPT_2, "tpt_ctl_fifo FIFO, channel 2" }, + { F_CAUSE_PCMD_DDP_2, "ddp_ctl_fifo FIFO, channel 2" }, + { F_CAUSE_PCMD_MPAR_2, "mpar_ctl_fifo FIFO, channel 2" }, + { F_CAUSE_PCMD_MPAC_2, "mpac_ctl_fifo FIFO, channel 2" }, + { F_CAUSE_PCMD_SFIFO_1, "Small FIFOs, channel 1" }, + { F_CAUSE_PCMD_FIFO_1, "pcmd_ctl_fifo, channel 1" }, + { F_CAUSE_PCMD_DDP_HINT_1, "ddp_hint_ctl_fifo FIFO, channel 1" }, + { F_CAUSE_PCMD_TPT_1, "tpt_ctl_fifo FIFO, channel 1" }, + { F_CAUSE_PCMD_DDP_1, "ddp_ctl_fifo FIFO, channel 1" }, + { F_CAUSE_PCMD_MPAR_1, "mpar_ctl_fifo FIFO, channel 1" }, + { F_CAUSE_PCMD_MPAC_1, "mpac_ctl_fifo FIFO, channel 1" }, + { F_CAUSE_PCMD_SFIFO_0, "Small FIFOs, channel 0" }, + { F_CAUSE_PCMD_FIFO_0, "pcmd_ctl_fifo, channel 0" }, + { F_CAUSE_PCMD_DDP_HINT_0, "ddp_hint_ctl_fifo FIFO, channel 0" }, + { F_CAUSE_PCMD_TPT_0, "tpt_ctl_fifo FIFO, channel 0" }, + { F_CAUSE_PCMD_DDP_0, "ddp_ctl_fifo FIFO, channel 0" }, + { F_CAUSE_PCMD_MPAR_0, "mpar_ctl_fifo FIFO, channel 0" }, + { F_CAUSE_PCMD_MPAC_0, "mpac_ctl_fifo FIFO, channel 0" }, + { 0 } + }; static const struct intr_info ulprx_int_cause_pcmd = { .name = "ULP_RX_INT_CAUSE_PCMD", .cause_reg = A_ULP_RX_INT_CAUSE_PCMD, .enable_reg = A_ULP_RX_INT_ENABLE_PCMD, .fatal = 0, .flags = 0, - .details = NULL, + .details = ulprx_int_cause_pcmd_details, .actions = NULL, }; + static const struct intr_details ulprx_int_cause_data_details[] = { + { F_CAUSE_DATA_SNOOP_3, "Snoop FIFO, channel 3" }, + { F_CAUSE_DATA_SFIFO_3, "Small FIFO, channel 3" }, + { F_CAUSE_DATA_FIFO_3, "data_ctl_fifo FIFO, channel 3" }, + { F_CAUSE_DATA_DDP_3, "ddp_ctl_fifo FIFO, channel 3" }, + { F_CAUSE_DATA_CTX_3, "ctx_ctl_fifo FIFO, channel 3" }, + { F_CAUSE_DATA_PARSER_3, "parser_ctl_fifo FIFO, channel 3" }, + { F_CAUSE_DATA_SNOOP_2, "Snoop FIFO, channel 2" }, + { F_CAUSE_DATA_SFIFO_2, "Small FIFO, channel 2" }, + { F_CAUSE_DATA_FIFO_2, "data_ctl_fifo FIFO, channel 2" }, + { F_CAUSE_DATA_DDP_2, "ddp_ctl_fifo FIFO, channel 2" }, + { F_CAUSE_DATA_CTX_2, "ctx_ctl_fifo FIFO, channel 2" }, + { F_CAUSE_DATA_PARSER_2, "parser_ctl_fifo FIFO, channel 2" }, + { F_CAUSE_DATA_SNOOP_1, "Snoop FIFO, channel 1" }, + { F_CAUSE_DATA_SFIFO_1, "Small FIFO, channel 1" }, + { F_CAUSE_DATA_FIFO_1, "data_ctl_fifo FIFO, channel 1" }, + { F_CAUSE_DATA_DDP_1, "ddp_ctl_fifo FIFO, channel 1" }, + { F_CAUSE_DATA_CTX_1, "ctx_ctl_fifo FIFO, channel 1" }, + { F_CAUSE_DATA_PARSER_1, "parser_ctl_fifo FIFO, channel 1" }, + { F_CAUSE_DATA_SNOOP_0, "Snoop FIFO, channel 0" }, + { F_CAUSE_DATA_SFIFO_0, "Small FIFO, channel 0" }, + { F_CAUSE_DATA_FIFO_0, "data_ctl_fifo FIFO, channel 0" }, + { F_CAUSE_DATA_DDP_0, "ddp_ctl_fifo FIFO, channel 0" }, + { F_CAUSE_DATA_CTX_0, "ctx_ctl_fifo FIFO, channel 0" }, + { F_CAUSE_DATA_PARSER_0, "parser_ctl_fifo FIFO, channel 0" }, + { 0 } + }; static const struct intr_info ulprx_int_cause_data = { .name = "ULP_RX_INT_CAUSE_DATA", .cause_reg = A_ULP_RX_INT_CAUSE_DATA, .enable_reg = A_ULP_RX_INT_ENABLE_DATA, .fatal = 0, .flags = 0, - .details = NULL, + .details = ulprx_int_cause_data_details, .actions = NULL, }; + static const struct intr_details ulprx_int_cause_arb_details[] = { + { F_CAUSE_ARB_PBL_PF_3, "pbl_pf_ctl_fifo FIFO, channel 3" }, + { F_CAUSE_ARB_PF_3, "pf_ctl_fifo FIFO, channel 3" }, + { F_CAUSE_ARB_TPT_PF_3, "tpt_pf_ctl_fifo FIFO, channel 3" }, + { F_CAUSE_ARB_F_3, "f_ctl_fifo FIFO, channel 3" }, + { F_CAUSE_ARB_PBL_PF_2, "pbl_pf_ctl_fifo FIFO, channel 2" }, + { F_CAUSE_ARB_PF_2, "pf_ctl_fifo FIFO, channel 2" }, + { F_CAUSE_ARB_TPT_PF_2, "tpt_pf_ctl_fifo FIFO, channel 2" }, + { F_CAUSE_ARB_F_2, "f_ctl_fifo FIFO, channel 2" }, + { F_CAUSE_ARB_PBL_PF_1, "pbl_pf_ctl_fifo FIFO, channel 1" }, + { F_CAUSE_ARB_PF_1, "pf_ctl_fifo FIFO, channel 1" }, + { F_CAUSE_ARB_TPT_PF_1, "tpt_pf_ctl_fifo FIFO, channel 1" }, + { F_CAUSE_ARB_F_1, "f_ctl_fifo FIFO, channel 1" }, + { F_CAUSE_ARB_PBL_PF_0, "pbl_pf_ctl_fifo FIFO, channel 0" }, + { F_CAUSE_ARB_PF_0, "pf_ctl_fifo FIFO, channel 0" }, + { F_CAUSE_ARB_TPT_PF_0, "tpt_pf_ctl_fifo FIFO, channel 0" }, + { F_CAUSE_ARB_F_0, "f_ctl_fifo FIFO, channel 0" }, + { 0 } + }; static const struct intr_info ulprx_int_cause_arb = { .name = "ULP_RX_INT_CAUSE_ARB", .cause_reg = A_ULP_RX_INT_CAUSE_ARB, .enable_reg = A_ULP_RX_INT_ENABLE_ARB, .fatal = 0, .flags = 0, - .details = NULL, + .details = ulprx_int_cause_arb_details, .actions = NULL, }; + static const struct intr_details ulprx_int_cause_interface_details[] = { + { F_CAUSE_ULPRX2SBT_RSPPERR, "ULPRX2SBT_RspPerr" }, + { F_CAUSE_ULPRX2MA_RSPPERR, "ULPRX2MA_RspPerr" }, + { F_CAUSE_PIO_BUS_PERR, "Pio_Bus_Perr" }, + { F_CAUSE_PM2ULP_SNOOPDATA_3, "PM2ULP_SnoopData, channel 3" }, + { F_CAUSE_PM2ULP_SNOOPDATA_2, "PM2ULP_SnoopData, channel 2" }, + { F_CAUSE_PM2ULP_SNOOPDATA_1, "PM2ULP_SnoopData, channel 1" }, + { F_CAUSE_PM2ULP_SNOOPDATA_0, "PM2ULP_SnoopData, channel 0" }, + { F_CAUSE_TLS2ULP_DATA_3, "TLS2ULP_Data, channel 3" }, + { F_CAUSE_TLS2ULP_DATA_2, "TLS2ULP_Data, channel 2" }, + { F_CAUSE_TLS2ULP_DATA_1, "TLS2ULP_Data, channel 1" }, + { F_CAUSE_TLS2ULP_DATA_0, "TLS2ULP_Data, channel 0" }, + { F_CAUSE_TLS2ULP_PLENDATA_3, "TLS2ULP_PLenData, channel 3" }, + { F_CAUSE_TLS2ULP_PLENDATA_2, "TLS2ULP_PLenData, channel 2" }, + { F_CAUSE_TLS2ULP_PLENDATA_1, "TLS2ULP_PLenData, channel 1" }, + { F_CAUSE_TLS2ULP_PLENDATA_0, "TLS2ULP_PLenData, channel 0" }, + { F_CAUSE_PM2ULP_DATA_3, "Pm2Ulp_Data, channel 3" }, + { F_CAUSE_PM2ULP_DATA_2, "Pm2Ulp_Data, channel 2" }, + { F_CAUSE_PM2ULP_DATA_1, "Pm2Ulp_Data, channel 1" }, + { F_CAUSE_PM2ULP_DATA_0, "Pm2Ulp_Data, channel 0" }, + { F_CAUSE_TP2ULP_PCMD_3, "Tp2Ulp_Pcmd, channel 3" }, + { F_CAUSE_TP2ULP_PCMD_2, "Tp2Ulp_Pcmd, channel 2" }, + { F_CAUSE_TP2ULP_PCMD_1, "Tp2Ulp_Pcmd, channel 1" }, + { F_CAUSE_TP2ULP_PCMD_0, "Tp2Ulp_Pcmd, channel 0" }, + { 0 } + }; static const struct intr_info ulprx_int_cause_intf = { .name = "ULP_RX_INT_CAUSE_INTERFACE", .cause_reg = A_ULP_RX_INT_CAUSE_INTERFACE, .enable_reg = A_ULP_RX_INT_ENABLE_INTERFACE, .fatal = 0, .flags = 0, - .details = NULL, + .details = ulprx_int_cause_interface_details, .actions = NULL, }; bool fatal = false; + if (chip_id(adap) <= CHELSIO_T5) + ulprx_intr_info.details = ulprx_intr_details; + else if (chip_id(adap) <= CHELSIO_T6) + ulprx_intr_info.details = t6_ulprx_int_cause_details; + else + ulprx_intr_info.details = t7_ulprx_int_cause_details; + fatal |= t4_handle_intr(adap, &ulprx_intr_info, 0, flags); if (chip_id(adap) < CHELSIO_T7) fatal |= t4_handle_intr(adap, &ulprx_intr2_info, 0, flags); @@ -5559,90 +6241,298 @@ static bool ulptx_intr_handler(struct adapter *adap, int arg, int flags) { 0x0fffffff, "ULPTX parity error" }, { 0 } }; - static const struct intr_info ulptx_intr_info = { + static const struct intr_details t6_ulptx_int_cause_details[] = { + { F_PBL_BOUND_ERR_CH3 | F_PBL_BOUND_ERR_CH2 | + F_PBL_BOUND_ERR_CH1 | F_PBL_BOUND_ERR_CH0, + "PBL address out of bounds" }, + { F_SGE2ULP_FIFO_PERR_SET3 | F_SGE2ULP_FIFO_PERR_SET2 | + F_SGE2ULP_FIFO_PERR_SET1 | F_SGE2ULP_FIFO_PERR_SET0, + "SGE2ULP fifo parity error" }, + { F_CIM2ULP_FIFO_PERR_SET3 | F_CIM2ULP_FIFO_PERR_SET2 | + F_CIM2ULP_FIFO_PERR_SET1 | F_CIM2ULP_FIFO_PERR_SET0, + "CIM2ULP fifo parity error" }, + { F_CQE_FIFO_PERR_SET3 | F_CQE_FIFO_PERR_SET2 | + F_CQE_FIFO_PERR_SET1 | F_CQE_FIFO_PERR_SET0, + "CQE fifo parity error" }, + { F_PBL_FIFO_PERR_SET3 | F_PBL_FIFO_PERR_SET2 | + F_PBL_FIFO_PERR_SET1 | F_PBL_FIFO_PERR_SET0, + "PBL fifo parity error" }, + { F_CMD_FIFO_PERR_SET3 | F_CMD_FIFO_PERR_SET2 | + F_CMD_FIFO_PERR_SET1 | F_CMD_FIFO_PERR_SET0, + "Command fifo parity error" }, + { F_LSO_HDR_SRAM_PERR_SET3 | F_LSO_HDR_SRAM_PERR_SET2 | + F_LSO_HDR_SRAM_PERR_SET1 | F_LSO_HDR_SRAM_PERR_SET0, + "LSO hdr parity error" }, + { 0 } + }; + struct intr_info ulptx_intr_info = { .name = "ULP_TX_INT_CAUSE", .cause_reg = A_ULP_TX_INT_CAUSE, .enable_reg = A_ULP_TX_INT_ENABLE, .fatal = 0x0fffffff, .flags = IHF_FATAL_IFF_ENABLED, - .details = ulptx_intr_details, + .details = NULL, + .actions = NULL, + }; + static const struct intr_details ulptx_int_cause_1_details[] = { + { F_PBL_BOUND_ERR_CH3 | F_PBL_BOUND_ERR_CH2 | + F_PBL_BOUND_ERR_CH1 | F_PBL_BOUND_ERR_CH0, + "PBL address out of bounds (configured PBL_ULIMIT/LLIMIT)" }, + { F_SGE2ULP_FIFO_PERR_SET3 | F_SGE2ULP_FIFO_PERR_SET2 | + F_SGE2ULP_FIFO_PERR_SET1 | F_SGE2ULP_FIFO_PERR_SET0, + "SGE2ULP FIFO parity error" }, + { F_CIM2ULP_FIFO_PERR_SET3 | F_CIM2ULP_FIFO_PERR_SET2 | + F_CIM2ULP_FIFO_PERR_SET1 | F_CIM2ULP_FIFO_PERR_SET0, + "CIM2ULP FIFO parity error" }, + { F_CQE_FIFO_PERR_SET3 | F_CQE_FIFO_PERR_SET2 | + F_CQE_FIFO_PERR_SET1 | F_CQE_FIFO_PERR_SET0, + "CQE FIFO parity error" }, + { F_PBL_FIFO_PERR_SET3 | F_PBL_FIFO_PERR_SET2 | + F_PBL_FIFO_PERR_SET1 | F_PBL_FIFO_PERR_SET0, + "PBL FIFO parity error" }, + { F_CMD_FIFO_PERR_SET3 | F_CMD_FIFO_PERR_SET2 | + F_CMD_FIFO_PERR_SET1 | F_CMD_FIFO_PERR_SET0, + "Command FIFO parity error" }, + { F_LSO_HDR_SRAM_PERR_SET3 | F_LSO_HDR_SRAM_PERR_SET2 | + F_LSO_HDR_SRAM_PERR_SET1 | F_LSO_HDR_SRAM_PERR_SET0, + "LSO HDR parity error" }, + { F_TLS_DSGL_PARERR3 | F_TLS_DSGL_PARERR2 | + F_TLS_DSGL_PARERR1 | F_TLS_DSGL_PARERR0, + "TLS Glue DSGL FIFO parity error" }, + { 0 } + }; + static const struct intr_info ulptx_intr_info1 = { + .name = "ULP_TX_INT_CAUSE_1", + .cause_reg = A_ULP_TX_INT_CAUSE_1, + .enable_reg = A_ULP_TX_INT_ENABLE_1, + .fatal = 0x0fffffff, + .flags = IHF_FATAL_IFF_ENABLED, + .details = ulptx_int_cause_1_details, .actions = NULL, }; + static const struct intr_details ulptx_int_cause_2_details[] = { + { F_EDMA_IN_FIFO_PERR_SET3 | F_EDMA_IN_FIFO_PERR_SET2 | + F_EDMA_IN_FIFO_PERR_SET1 | F_EDMA_IN_FIFO_PERR_SET0, + "EDMA input FIFO parity error" }, + { F_ALIGN_CTL_FIFO_PERR_SET3 | F_ALIGN_CTL_FIFO_PERR_SET2 | + F_ALIGN_CTL_FIFO_PERR_SET1 | F_ALIGN_CTL_FIFO_PERR_SET0, + "Align control FIFO parity error" }, + { F_SGE_FIFO_PERR_SET3 | F_SGE_FIFO_PERR_SET2 | + F_SGE_FIFO_PERR_SET1 | F_SGE_FIFO_PERR_SET0, + "SGE FIFO parity error" }, + { F_STAG_FIFO_PERR_SET3 | F_STAG_FIFO_PERR_SET2 | + F_STAG_FIFO_PERR_SET1 | F_STAG_FIFO_PERR_SET0, + "STAG FIFO parity error" }, + { F_MAP_FIFO_PERR_SET3 | F_MAP_FIFO_PERR_SET2 | + F_MAP_FIFO_PERR_SET1 | F_MAP_FIFO_PERR_SET0, + "MAP FIFO parity error" }, + { F_DMA_FIFO_PERR_SET3 | F_DMA_FIFO_PERR_SET2 | + F_DMA_FIFO_PERR_SET1 | F_DMA_FIFO_PERR_SET0, + "DMA FIFO parity error" }, + { F_FSO_HDR_SRAM_PERR_SET3 | F_FSO_HDR_SRAM_PERR_SET2 | + F_FSO_HDR_SRAM_PERR_SET1 | F_FSO_HDR_SRAM_PERR_SET0, + "FSO HDR memory parity error" }, + { F_T10_PI_SRAM_PERR_SET3 | F_T10_PI_SRAM_PERR_SET2 | + F_T10_PI_SRAM_PERR_SET1 | F_T10_PI_SRAM_PERR_SET0, + "T10 PI memory parity error" }, + { 0 } + }; static const struct intr_info ulptx_intr_info2 = { .name = "ULP_TX_INT_CAUSE_2", .cause_reg = A_ULP_TX_INT_CAUSE_2, .enable_reg = A_ULP_TX_INT_ENABLE_2, .fatal = 0xffffffff, .flags = IHF_FATAL_IFF_ENABLED, - .details = NULL, + .details = ulptx_int_cause_2_details, .actions = NULL, }; + static const struct intr_details ulptx_int_cause_3_details[] = { + { F_GF_SGE_FIFO_PARERR3 | F_GF_SGE_FIFO_PARERR2 | + F_GF_SGE_FIFO_PARERR1 | F_GF_SGE_FIFO_PARERR0, + "GF SGE interface FIFO parity error" }, + { F_DEDUPE_SGE_FIFO_PARERR3 | F_DEDUPE_SGE_FIFO_PARERR2 | + F_DEDUPE_SGE_FIFO_PARERR1 | F_DEDUPE_SGE_FIFO_PARERR0, + "DeDupe SGE interface FIFO parity error" }, + { F_GF3_DSGL_FIFO_PARERR | F_GF2_DSGL_FIFO_PARERR | + F_GF1_DSGL_FIFO_PARERR | F_GF0_DSGL_FIFO_PARERR, + "GF DSGL FIFO parity error" }, + { F_DEDUPE3_DSGL_FIFO_PARERR | F_DEDUPE2_DSGL_FIFO_PARERR | + F_DEDUPE1_DSGL_FIFO_PARERR | F_DEDUPE0_DSGL_FIFO_PARERR, + "DeDupe DSGL FIFO parity error" }, + { F_XP10_SGE_FIFO_PARERR, "XP10 SGE FIFO parity error (Ch0)" }, + { F_DSGL_PAR_ERR, "XP10 DSGL interface parity error" }, + { F_CDDIP_INT, "XP10 decompression interrupt" }, + { F_CCEIP_INT, "XP10 compression interrupt" }, + { F_TLS_SGE_FIFO_PARERR3 | F_TLS_SGE_FIFO_PARERR2 | + F_TLS_SGE_FIFO_PARERR1 | F_TLS_SGE_FIFO_PARERR0, + "TLS Glue SGE FIFO parity error" }, + { F_ULP2SMARBT_RSP_PERR, "ULP2SMARBT response data/CTL parity error" }, + { F_ULPTX2MA_RSP_PERR, "ULP2MA response data/CTL parity error" }, + { F_PCIE2ULP_PERR3 | F_PCIE2ULP_PERR2 | + F_PCIE2ULP_PERR1 | F_PCIE2ULP_PERR0, + "PCIE2ULP EDMA response parity error" }, + { F_CIM2ULP_PERR, "CIM2ULP command parity error (all ports)" }, + { 0 } + }; static const struct intr_info ulptx_intr_info3 = { .name = "ULP_TX_INT_CAUSE_3", .cause_reg = A_ULP_TX_INT_CAUSE_3, .enable_reg = A_ULP_TX_INT_ENABLE_3, .fatal = 0xffffffff, .flags = IHF_FATAL_IFF_ENABLED, - .details = NULL, + .details = ulptx_int_cause_3_details, .actions = NULL, }; + static const struct intr_details ulptx_int_cause_4_details[] = { + { F_XP10_2_ULP_PERR, "XP10 to ULP parity error" }, + { F_ULP_2_XP10_PERR, "ULP to XP10 parity error" }, + { F_CMD_FIFO_LB1 | F_CMD_FIFO_LB0, + "Command FIFO LB error" }, + { F_TF_TP_PERR, "TF TP parity error" }, + { F_TF_SGE_PERR, "TF SGE parity error" }, + { F_TF_MEM_PERR, "TF memory parity error" }, + { F_TF_MP_PERR, "TF MP parity error" }, + { 0 } + }; static const struct intr_info ulptx_intr_info4 = { .name = "ULP_TX_INT_CAUSE_4", .cause_reg = A_ULP_TX_INT_CAUSE_4, .enable_reg = A_ULP_TX_INT_ENABLE_4, .fatal = 0xffffffff, .flags = IHF_FATAL_IFF_ENABLED, - .details = NULL, + .details = ulptx_int_cause_4_details, .actions = NULL, }; + static const struct intr_details ulptx_int_cause_5_details[] = { + { F_DEDUPE_PERR3 | F_DEDUPE_PERR2 | + F_DEDUPE_PERR1 | F_DEDUPE_PERR0, + "DeDupe parity error" }, + { F_GF_PERR3 | F_GF_PERR2 | + F_GF_PERR1 | F_GF_PERR0, + "GF parity error" }, + { F_SGE2ULP_INV_PERR, "SGE2ULP invalid parity error" }, + { F_T7_PL_BUSPERR, "PL bus parity error" }, + { F_TLSTX2ULPTX_PERR3 | F_TLSTX2ULPTX_PERR2 | + F_TLSTX2ULPTX_PERR1 | F_TLSTX2ULPTX_PERR0, + "TLS to ULP parity error" }, + { F_XP10_2_ULP_PL_PERR, "XP10 to ULP PL parity error" }, + { F_ULP_2_XP10_PL_PERR, "ULP to XP10 PL parity error" }, + { 0 } + }; static const struct intr_info ulptx_intr_info5 = { .name = "ULP_TX_INT_CAUSE_5", .cause_reg = A_ULP_TX_INT_CAUSE_5, .enable_reg = A_ULP_TX_INT_ENABLE_5, .fatal = 0xffffffff, .flags = IHF_FATAL_IFF_ENABLED, - .details = NULL, + .details = ulptx_int_cause_5_details, .actions = NULL, }; + static const struct intr_details ulptx_int_cause_6_details[] = { + { F_DDR_HDR_FIFO_PERR_SET3 | F_DDR_HDR_FIFO_PERR_SET2 | + F_DDR_HDR_FIFO_PERR_SET1 | F_DDR_HDR_FIFO_PERR_SET0, + "DDR HDR FIFO parity error" }, + { F_PRE_MP_RSP_PERR_SET3 | F_PRE_MP_RSP_PERR_SET2 | + F_PRE_MP_RSP_PERR_SET1 | F_PRE_MP_RSP_PERR_SET0, + "Pre-MP response parity error" }, + { F_PRE_CQE_FIFO_PERR_SET3 | F_PRE_CQE_FIFO_PERR_SET2 | + F_PRE_CQE_FIFO_PERR_SET1 | F_PRE_CQE_FIFO_PERR_SET0, + "Pre-CQE FIFO parity error" }, + { F_RSP_FIFO_PERR_SET, "Response FIFO parity error" }, + { 0 } + }; static const struct intr_info ulptx_intr_info6 = { .name = "ULP_TX_INT_CAUSE_6", .cause_reg = A_ULP_TX_INT_CAUSE_6, .enable_reg = A_ULP_TX_INT_ENABLE_6, .fatal = 0xffffffff, .flags = IHF_FATAL_IFF_ENABLED, - .details = NULL, + .details = ulptx_int_cause_6_details, .actions = NULL, }; + static const struct intr_details ulptx_int_cause_7_details[] = { + { F_TLS_SGE_FIFO_CORERR3 | F_TLS_SGE_FIFO_CORERR2 | + F_TLS_SGE_FIFO_CORERR1 | F_TLS_SGE_FIFO_CORERR0, + "TLS SGE FIFO correctable error" }, + { F_LSO_HDR_SRAM_CERR_SET3 | F_LSO_HDR_SRAM_CERR_SET2 | + F_LSO_HDR_SRAM_CERR_SET1 | F_LSO_HDR_SRAM_CERR_SET0, + "LSO HDR SRAM correctable error" }, + { F_CORE_CMD_FIFO_CERR_SET_CH3_LB1 | F_CORE_CMD_FIFO_CERR_SET_CH2_LB1 | + F_CORE_CMD_FIFO_CERR_SET_CH1_LB1 | F_CORE_CMD_FIFO_CERR_SET_CH0_LB1, + "Core command FIFO LB1 correctable error" }, + { F_CORE_CMD_FIFO_CERR_SET_CH3_LB0 | F_CORE_CMD_FIFO_CERR_SET_CH2_LB0 | + F_CORE_CMD_FIFO_CERR_SET_CH1_LB0 | F_CORE_CMD_FIFO_CERR_SET_CH0_LB0, + "Core command FIFO LB0 correctable error" }, + { F_CQE_FIFO_CERR_SET3 | F_CQE_FIFO_CERR_SET2 | + F_CQE_FIFO_CERR_SET1 | F_CQE_FIFO_CERR_SET0, + "CQE FIFO correctable error" }, + { F_PRE_CQE_FIFO_CERR_SET3 | F_PRE_CQE_FIFO_CERR_SET2 | + F_PRE_CQE_FIFO_CERR_SET1 | F_PRE_CQE_FIFO_CERR_SET0, + "Pre-CQE FIFO correctable error" }, + { 0 } + }; static const struct intr_info ulptx_intr_info7 = { .name = "ULP_TX_INT_CAUSE_7", .cause_reg = A_ULP_TX_INT_CAUSE_7, .enable_reg = A_ULP_TX_INT_ENABLE_7, .fatal = 0, .flags = 0, - .details = NULL, + .details = ulptx_int_cause_7_details, .actions = NULL, }; + static const struct intr_details ulptx_int_cause_8_details[] = { + { F_MEM_RSP_FIFO_CERR_SET3 | F_MEM_RSP_FIFO_CERR_SET2 | + F_MEM_RSP_FIFO_CERR_SET1 | F_MEM_RSP_FIFO_CERR_SET0, + "Memory response FIFO correctable error" }, + { F_PI_SRAM_CERR_SET3 | F_PI_SRAM_CERR_SET2 | + F_PI_SRAM_CERR_SET1 | F_PI_SRAM_CERR_SET0, + "PI SRAM correctable error" }, + { F_PRE_MP_RSP_CERR_SET3 | F_PRE_MP_RSP_CERR_SET2 | + F_PRE_MP_RSP_CERR_SET1 | F_PRE_MP_RSP_CERR_SET0, + "Pre-MP response correctable error" }, + { F_DDR_HDR_FIFO_CERR_SET3 | F_DDR_HDR_FIFO_CERR_SET2 | + F_DDR_HDR_FIFO_CERR_SET1 | F_DDR_HDR_FIFO_CERR_SET0, + "DDR HDR FIFO correctable error" }, + { F_CMD_FIFO_CERR_SET3 | F_CMD_FIFO_CERR_SET2 | + F_CMD_FIFO_CERR_SET1 | F_CMD_FIFO_CERR_SET0, + "Command FIFO correctable error" }, + { F_GF_SGE_FIFO_CORERR3 | F_GF_SGE_FIFO_CORERR2 | + F_GF_SGE_FIFO_CORERR1 | F_GF_SGE_FIFO_CORERR0, + "GF SGE FIFO correctable error" }, + { F_DEDUPE_SGE_FIFO_CORERR3 | F_DEDUPE_SGE_FIFO_CORERR2 | + F_DEDUPE_SGE_FIFO_CORERR1 | F_DEDUPE_SGE_FIFO_CORERR0, + "DeDupe SGE FIFO correctable error" }, + { F_RSP_FIFO_CERR_SET, "Response FIFO correctable error" }, + { 0 } + }; static const struct intr_info ulptx_intr_info8 = { .name = "ULP_TX_INT_CAUSE_8", .cause_reg = A_ULP_TX_INT_CAUSE_8, .enable_reg = A_ULP_TX_INT_ENABLE_8, .fatal = 0, .flags = 0, - .details = NULL, + .details = ulptx_int_cause_8_details, .actions = NULL, }; bool fatal = false; - fatal |= t4_handle_intr(adap, &ulptx_intr_info, 0, flags); - if (chip_id(adap) > CHELSIO_T4) - fatal |= t4_handle_intr(adap, &ulptx_intr_info2, 0, flags); if (chip_id(adap) > CHELSIO_T6) { + fatal |= t4_handle_intr(adap, &ulptx_intr_info1, 0, flags); + fatal |= t4_handle_intr(adap, &ulptx_intr_info2, 0, flags); fatal |= t4_handle_intr(adap, &ulptx_intr_info3, 0, flags); fatal |= t4_handle_intr(adap, &ulptx_intr_info4, 0, flags); fatal |= t4_handle_intr(adap, &ulptx_intr_info5, 0, flags); fatal |= t4_handle_intr(adap, &ulptx_intr_info6, 0, flags); fatal |= t4_handle_intr(adap, &ulptx_intr_info7, 0, flags); fatal |= t4_handle_intr(adap, &ulptx_intr_info8, 0, flags); + } else { + if (chip_id(adap) == CHELSIO_T6) + ulptx_intr_info.details = t6_ulptx_int_cause_details; + else + ulptx_intr_info.details = ulptx_intr_details; + fatal |= t4_handle_intr(adap, &ulptx_intr_info, 0, flags); + if (chip_id(adap) > CHELSIO_T4) + fatal |= t4_handle_intr(adap, &ulptx_intr_info2, 0, flags); } return (fatal); @@ -5671,6 +6561,25 @@ static bool pmtx_dump_dbg_stats(struct adapter *adap, int arg, int flags) */ static bool pmtx_intr_handler(struct adapter *adap, int arg, int flags) { + static const struct intr_details t7_pmtx_int_cause_fields[] = { + { F_MASTER_PERR, "PM_TX master parity error" }, + { F_T7_ZERO_C_CMD_ERROR, "PM_TX PCMD with zero length error" }, + { F_OESPI_COR_ERR, " oespi FIFO Correctable Error" }, + { F_ICSPI_COR_ERR, " icspi FIFO Correctable Error" }, + { F_ICSPI_OVFL, " icspi FIFO overflow" }, + { F_T7_PCMD_LEN_OVFL0, "PMTX channel 0 pcmd too large" }, + { F_T7_PCMD_LEN_OVFL1, "PMTX channel 1 pcmd too large" }, + { F_T7_PCMD_LEN_OVFL2, "PMTX channel 2 pcmd too large" }, + { F_PCMD_LEN_OVFL3, "PMTX channel 2 pcmd too large" }, + { F_T7_ZERO_C_CMD_ERROR, "PMTX 0-length pcmd" }, + { 0x00f00000, "PM_TX PCMD length larger than oespi capacity" }, + { 0x000f0000, "PM_TX icspi 2x FIFO Rx framing error" }, + { 0x0000f000, "PM_TX icspi FIFO Tx framing error" }, + { 0x00000f00, "PM_TX oespi FIFO Rx framing error" }, + { 0x000000f0, "PM_TX oespi FIFO Tx framing error" }, + { 0x0000000f, "PM_TX oespi 2x FIFO Tx framing error" }, + { 0 } + }; static const struct intr_details pmtx_int_cause_fields[] = { { F_PCMD_LEN_OVFL0, "PMTX channel 0 pcmd too large" }, { F_PCMD_LEN_OVFL1, "PMTX channel 1 pcmd too large" }, @@ -5692,17 +6601,58 @@ static bool pmtx_intr_handler(struct adapter *adap, int arg, int flags) { 0xffffffff, -1, pmtx_dump_dbg_stats }, { 0 }, }; - static const struct intr_info pmtx_int_cause = { + struct intr_info pmtx_int_cause = { .name = "PM_TX_INT_CAUSE", .cause_reg = A_PM_TX_INT_CAUSE, .enable_reg = A_PM_TX_INT_ENABLE, .fatal = 0xffffffff, - .flags = 0, - .details = pmtx_int_cause_fields, + .flags = IHF_CLR_DELAYED, + .details = NULL, .actions = pmtx_int_cause_actions, }; + static const struct intr_details pmtx_perr_cause_details[] = { + { F_ICSPI_OVFL, "icspi FIFO Overflow" }, + { F_OSPI_OVERFLOW3_TX, " OSPI overflow on channel 3 error." }, + { F_OSPI_OVERFLOW2_TX, " OSPI overflow on channel 2 error." }, + { F_OSPI_OVERFLOW1_TX, " OSPI overflow on channel 1 error." }, + { F_OSPI_OVERFLOW0_TX, " OSPI overflow on channel 0 error." }, + { F_T7_BUNDLE_LEN_OVFL_EN, "This bit indicates bundle_len_ovfl_err." }, + { F_T7_M_INTFPERREN, "This bit indicates Parity error from MA interfaces." }, + { F_T7_1_SDC_ERR, + "SDC Error reported by Check PCMD which carries CRC16 from TP-CSide." }, + { F_MC_WCNT_FIFO_PERR, "MC Interface Write count FIFO Parity error" }, + { F_MC_WDATA_FIFO_PERR, "MC Interface Write Data FIFO Parity error" }, + { F_MC_RCNT_FIFO_PERR, "MC Interface Read count FIFO Parity error" }, + { F_MC_RDATA_FIFO_PERR, "MC Interface Read Data FIFO Parity error" }, + { F_TOKEN_PAR_ERROR, "c_pcmd, Token FIFO par error" }, + { F_BUNDLE_LEN_PAR_ERROR, "oespi par error" }, + { F_OESPI_PAR_ERROR, "oespi par error" }, + { F_DB_OPTIONS_PAR_ERROR, "db_options par error" }, + { F_ICSPI_PAR_ERROR, "icspi par error" }, + { F_C_PCMD_TOKEN_PAR_ERROR, "c_pcmd par error" }, + { 0 } + }; + static struct intr_info pmtx_perr_cause = { + .name = "PM_TX_PERR_CAUSE", + .cause_reg = A_PM_TX_PERR_CAUSE, + .enable_reg = A_PM_TX_PERR_ENABLE, + .fatal = 0xffffffff, + .flags = 0, + .details = pmtx_perr_cause_details, + .actions = NULL, + }; + bool fatal; + + if (chip_id(adap) >= CHELSIO_T7) + pmtx_int_cause.details = t7_pmtx_int_cause_fields; + else + pmtx_int_cause.details = pmtx_int_cause_fields; + fatal = t4_handle_intr(adap, &pmtx_int_cause, 0, flags); + if (chip_id(adap) >= CHELSIO_T7) + fatal |= t4_handle_intr(adap, &pmtx_perr_cause, 0, flags); + clear_int_cause_reg(adap, &pmtx_int_cause, flags); - return (t4_handle_intr(adap, &pmtx_int_cause, 0, flags)); + return (fatal); } /* @@ -5710,6 +6660,20 @@ static bool pmtx_intr_handler(struct adapter *adap, int arg, int flags) */ static bool pmrx_intr_handler(struct adapter *adap, int arg, int flags) { + static const struct intr_details t7_pmrx_int_cause_fields[] = { + { F_MASTER_PERR, "PM_RX master parity error" }, + { 0x18000000, "PMRX ospi overflow" }, + { F_BUNDLE_LEN_OVFL, "PMRX bundle len FIFO overflow" }, + { F_SDC_ERR, "PMRX SDC error" }, + { F_ZERO_E_CMD_ERROR, "PMRX 0-length pcmd" }, + { 0x003c0000, "PMRX iespi FIFO2X Rx framing error" }, + { 0x0003c000, "PMRX iespi Rx framing error" }, + { 0x00003c00, "PMRX iespi Tx framing error" }, + { 0x00000300, "PMRX ocspi Rx framing error" }, + { 0x000000c0, "PMRX ocspi Tx framing error" }, + { 0x00000030, "PMRX ocspi FIFO2X Tx framing error" }, + { 0 } + }; static const struct intr_details pmrx_int_cause_fields[] = { /* T6+ */ { 0x18000000, "PMRX ospi overflow" }, @@ -5732,17 +6696,90 @@ static bool pmrx_intr_handler(struct adapter *adap, int arg, int flags) { F_E_PCMD_PAR_ERROR, "PMRX e_pcmd parity error"}, { 0 } }; - static const struct intr_info pmrx_int_cause = { + struct intr_info pmrx_int_cause = { .name = "PM_RX_INT_CAUSE", .cause_reg = A_PM_RX_INT_CAUSE, .enable_reg = A_PM_RX_INT_ENABLE, .fatal = 0x1fffffff, + .flags = IHF_FATAL_IFF_ENABLED | IHF_CLR_DELAYED, + .details = NULL, + .actions = NULL, + }; + static const struct intr_details pm_rx_int_cause_2_details[] = { + { F_CACHE_SRAM_ODD_CERR, "Cache Data Odd SRAM Correctable Error" }, + { F_CACHE_SRAM_EVEN_CERR, "Cache Data Even SRAM Correctable Error" }, + { F_CACHE_LRU_LEFT_CERR, "Cache LRU Left SRAM Correctable Error" }, + { F_CACHE_LRU_RIGHT_CERR, "Cache LRU Right SRAM Correctable Error" }, + { F_CACHE_ISLAND_CERR, "Cache Island SRAM Correctable Error" }, + { F_OCSPI_CERR, "ocspi FIFO Correctable Error" }, + { F_IESPI_CERR, "iespi FIFO Correctable Error" }, + { F_OCSPI2_RX_FRAMING_ERROR, "ocspi FIFO channel 2 Rx/wr framing error" }, + { F_OCSPI3_RX_FRAMING_ERROR, "ocspi FIFO channel 3 Rx/wr framing error" }, + { F_OCSPI2_TX_FRAMING_ERROR, "ocspi FIFO channel 2 Tx/rd framing error" }, + { F_OCSPI3_TX_FRAMING_ERROR, "ocspi FIFO channel 3 Tx/rd framing error" }, + { F_OCSPI2_OFIFO2X_TX_FRAMING_ERROR, "ocspi 2x FIFO 2 Tx/rd framing error" }, + { F_OCSPI3_OFIFO2X_TX_FRAMING_ERROR, "ocspi 2x FIFO 3 Tx/rd framing error" }, + { 0 } + }; + static struct intr_info pmrx_int_cause2 = { + .name = "PM_RX_INT_CAUSE_2", + .cause_reg = A_PM_RX_INT_CAUSE_2, + .enable_reg = A_PM_RX_INT_ENABLE_2, + .fatal = 0x1fffffff, + .flags = IHF_FATAL_IFF_ENABLED, + .details = pm_rx_int_cause_2_details, + .actions = NULL, + }; + static const struct intr_details pm_rx_perr_cause_details[] = { + { F_T7_SDC_ERR, "SDC error. CRC provided by TP and PM didn't match." }, + { F_T7_MA_INTF_SDC_ERR, "MA intf SDC perr" }, + { F_E_PCMD_PERR, "ulp_rx 2 pm_rx PCMD interface parity error." }, + { F_CACHE_RSP_DFIFO_PERR, "Cache Response Data FIFO Parity error" }, + { F_CACHE_SRAM_ODD_PERR, "Cache Odd SRAM error" }, + { F_CACHE_SRAM_EVEN_PERR, "Cache Even SRAM error" }, + { F_CACHE_RSVD_PERR, "Cache Reserved Parity error" }, + { F_CACHE_LRU_LEFT_PERR, "Cache LRU Left SRAM error" }, + { F_CACHE_LRU_RIGHT_PERR, "Cache LRU Rigth SRAM error" }, + { F_CACHE_RSP_CMD_PERR, "Cache Response Command FIFO error" }, + { F_CACHE_SRAM_CMD_PERR, "Cache SRAM Command FIFO error" }, + { F_CACHE_MA_CMD_PERR, "Cache MA Command FIFO error" }, + { F_CACHE_TCAM_PERR, "Cache TCAM Parity error" }, + { F_CACHE_ISLAND_PERR, "Cache island SRAM Parity error" }, + { F_MC_WCNT_FIFO_PERR, "MC Interface Write count FIFO Parity error" }, + { F_MC_WDATA_FIFO_PERR, "MC Interface Write Data FIFO Parity error" }, + { F_MC_RCNT_FIFO_PERR, "MC Interface Read count FIFO Parity error" }, + { F_MC_RDATA_FIFO_PERR, "MC Interface Read Data FIFO Parity error" }, + { F_TOKEN_FIFO_PERR, "Token FIFO Parity error" }, + { F_T7_BUNDLE_LEN_PARERR, "Bundle len fifo had parity error." }, + { F_OCSPI_PAR_ERROR, "ocspi par error vector" }, + { F_DB_OPTIONS_PAR_ERROR, "db_options par error" }, + { F_IESPI_PAR_ERROR, "iespi par error" }, + { F_E_PCMD_PAR_ERROR, "e_pcmd par error" }, + { 0 } + }; + static struct intr_info pmrx_perr_cause = { + .name = "PM_RX_PERR_CAUSE", + .cause_reg = A_PM_RX_PERR_CAUSE, + .enable_reg = A_PM_RX_PERR_ENABLE, + .fatal = 0x1fffffff, .flags = IHF_FATAL_IFF_ENABLED, - .details = pmrx_int_cause_fields, + .details = pm_rx_perr_cause_details, .actions = NULL, }; + bool fatal; + + if (chip_id(adap) >= CHELSIO_T7) { + pmrx_int_cause.details = t7_pmrx_int_cause_fields; + fatal = t4_handle_intr(adap, &pmrx_int_cause, 0, flags); + fatal |= t4_handle_intr(adap, &pmrx_int_cause2, 0, flags); + fatal |= t4_handle_intr(adap, &pmrx_perr_cause, 0, flags); + } else { + pmrx_int_cause.details = pmrx_int_cause_fields; + fatal = t4_handle_intr(adap, &pmrx_int_cause, 0, flags); + } + clear_int_cause_reg(adap, &pmrx_int_cause, flags); - return (t4_handle_intr(adap, &pmrx_int_cause, 0, flags)); + return (fatal); } /* @@ -5751,6 +6788,9 @@ static bool pmrx_intr_handler(struct adapter *adap, int arg, int flags) static bool cplsw_intr_handler(struct adapter *adap, int arg, int flags) { static const struct intr_details cplsw_int_cause_fields[] = { + /* T7+ */ + { F_PERR_CPL_128TO128_3, "CPLSW 128TO128 FIFO3 parity error" }, + { F_PERR_CPL_128TO128_2, "CPLSW 128TO128 FIFO2 parity error" }, /* T5+ */ { F_PERR_CPL_128TO128_1, "CPLSW 128TO128 FIFO1 parity error" }, { F_PERR_CPL_128TO128_0, "CPLSW 128TO128 FIFO0 parity error" }, @@ -5803,6 +6843,8 @@ static bool le_intr_handler(struct adapter *adap, int arg, int flags) { 0 } }; static const struct intr_details t6_le_intr_details[] = { + { F_CACHEINTPERR, "Parity error in cache module" }, + { F_CACHESRAMPERR, "Parity error in data sram " }, { F_CLIPSUBERR, "LE CLIP CAM reverse substitution error" }, { F_CLCAMFIFOERR, "LE CLIP CAM internal FIFO error" }, { F_CTCAMINVLDENT, "Invalid IPv6 CLIP TCAM entry" }, @@ -5865,51 +6907,206 @@ static bool mps_intr_handler(struct adapter *adap, int arg, int flags) .details = mps_rx_perr_intr_details, .actions = NULL, }; + static const struct intr_details mps_rx_func_intr_details[] = { + { F_MTU_ERR3, "MTU error interrupt enable bit for loopback group 3" }, + { F_MTU_ERR2, "MTU error interrupt enable bit for loopback group 2" }, + { F_MTU_ERR1, "MTU error interrupt enable bit for loopback group 1" }, + { F_MTU_ERR0, "MTU error interrupt enable bit for loopback group 0" }, + { F_DBG_LEN_ERR, "Oring of len error in traffic transfer b/w internal modules" }, + { F_DBG_SPI_ERR, "Oring of spi error in traffic transfer b/w internal modules" }, + { F_DBG_SE_CNT_ERR, "Oring of se cnt error in traffic transfer" }, + { F_DBG_SPI_LEN_SE_CNT_ERR, "Oring of all se_cnt|len|spi errors" }, + { 0 } + }; + static const struct intr_info mps_rx_func_intr_info = { + .name = "MPS_RX_FUNC_INT_CAUSE", + .cause_reg = A_MPS_RX_FUNC_INT_CAUSE, + .enable_reg = A_MPS_RX_FUNC_INT_ENABLE, + .fatal = 0xffffffff, + .flags = IHF_FATAL_IFF_ENABLED, + .details = mps_rx_func_intr_details, + .actions = NULL, + }; + static const struct intr_details mpsrx_int_cause_2_details[] = { + { F_CRYPTO2MPS_RX0_PERR | F_CRYPTO2MPS_RX1_PERR | + F_CRYPTO2MPS_RX2_PERR | F_CRYPTO2MPS_RX3_PERR, + "Crypto to MPS RX interface parity error" }, + { F_INIC2MPS_TX1_PERR | F_INIC2MPS_TX0_PERR, + "INIC to MPS TX interface parity error" }, + { F_XGMAC2MPS_RX1_PERR | F_XGMAC2MPS_RX0_PERR, + "XGMAC to MPS RX interface parity error" }, + { F_RX_FINAL_TF_FIFO_PERR, + "Final RX token FIFO output parity error" }, + { F_MPS_DWRR_FIFO_PERR, + "MPS DWRR MTU FIFO parity error" }, + { F_MAC_TF_FIFO_PERR, + "MAC token FIFO parity error" }, + { F_MAC2MPS_PT3_PERR | F_MAC2MPS_PT2_PERR | + F_MAC2MPS_PT1_PERR | F_MAC2MPS_PT0_PERR, + "MAC to MPS interface parity error" }, + { F_TP_LPBK_FIFO_PERR, "TP loopback FIFO parity error" }, + { F_TP_LPBK_TF_PERR, "Loopback token FIFO parity error" }, + { 0 } + }; static const struct intr_info mps_rx_perr_intr_info2 = { .name = "MPS_RX_PERR_INT_CAUSE2", .cause_reg = A_MPS_RX_PERR_INT_CAUSE2, .enable_reg = A_MPS_RX_PERR_INT_ENABLE2, .fatal = 0xffffffff, .flags = IHF_FATAL_IFF_ENABLED, - .details = NULL, + .details = mpsrx_int_cause_2_details, .actions = NULL, }; + static const struct intr_details mpsrx_int_cause_3_details[] = { + { F_FIFO_REPL_CH3_CERR | F_FIFO_REPL_CH2_CERR | + F_FIFO_REPL_CH1_CERR | F_FIFO_REPL_CH0_CERR, + "Replication FIFO ECC error" }, + { F_VLAN_FILTER_RAM_CERR, "VLAN filter SRAM ECC error" }, + { F_MPS_RX_TD_STAT_FIFO_PERR_CH3 | F_MPS_RX_TD_STAT_FIFO_PERR_CH2 | + F_MPS_RX_TD_STAT_FIFO_PERR_CH1 | F_MPS_RX_TD_STAT_FIFO_PERR_CH0, + "MPS RX TD status descriptor FIFO parity error" }, + { F_RPLCT_HDR_FIFO_IN_PERR_CH3 | F_RPLCT_HDR_FIFO_IN_PERR_CH2 | + F_RPLCT_HDR_FIFO_IN_PERR_CH1 | F_RPLCT_HDR_FIFO_IN_PERR_CH0, + "MPS RX replication header input FIFO parity error" }, + { F_ID_FIFO_IN_PERR_CH3 | F_ID_FIFO_IN_PERR_CH2 | + F_ID_FIFO_IN_PERR_CH1 | F_ID_FIFO_IN_PERR_CH0, + "MPS RX replication ID input FIFO parity error" }, + { F_DESC_HDR2_PERR_CH3 | F_DESC_HDR2_PERR_CH2 | + F_DESC_HDR2_PERR_CH1 | F_DESC_HDR2_PERR_CH0, + "MPS RX replication descriptor/header2 FIFO parity error" }, + { F_FIFO_REPL_PERR_CH3 | F_FIFO_REPL_PERR_CH2 | + F_FIFO_REPL_PERR_CH1 | F_FIFO_REPL_PERR_CH0, + "Replication FIFO parity error" }, + { F_MPS_RX_TD_PERR_CH3 | F_MPS_RX_TD_PERR_CH2 | + F_MPS_RX_TD_PERR_CH1 | F_MPS_RX_TD_PERR_CH0, + "MPS RX TD input FIFO parity error" }, + { 0 } + }; static const struct intr_info mps_rx_perr_intr_info3 = { .name = "MPS_RX_PERR_INT_CAUSE3", .cause_reg = A_MPS_RX_PERR_INT_CAUSE3, .enable_reg = A_MPS_RX_PERR_INT_ENABLE3, .fatal = 0xffffffff, .flags = IHF_FATAL_IFF_ENABLED, - .details = NULL, + .details = mpsrx_int_cause_3_details, .actions = NULL, }; + static const struct intr_details mpsrx_int_cause_4_details[] = { + { F_VNI_MULTICAST_FIFO_ECC_ERR_CH3 | F_VNI_MULTICAST_FIFO_ECC_ERR_CH2, + "RX out VNI multicast SRAM ECC error" }, + { F_HASH_SRAM_CLS_ENG1 | F_HASH_SRAM_CLS_ENG0, + "Classification engine hash SRAM ECC error" }, + { F_CLS_TCAM_SRAM_CLS_ENG1 | F_CLS_TCAM_SRAM_CLS_ENG0, + "Classification engine TCAM SRAM ECC error" }, + { F_CLS_TCAM_CRC_SRAM_CLS_ENG1 | F_CLS_TCAM_CRC_SRAM_CLS_ENG0, + "Classification engine TCAM CRC SRAM ECC error" }, + { F_DWRR_CH_FIFO_ECC_ERR, "DWRR output FIFO ECC error" }, + { F_MAC_RX_FIFO_ECC_ERR, "MAC RX FIFO ECC error" }, + { F_LPBK_RX_FIFO_ECC_ERR, "Loopback RX FIFO ECC error" }, + { F_CRS_DATA_STORE_N_FWD_CH3 | F_CRS_DATA_STORE_N_FWD_CH2 | + F_CRS_DATA_STORE_N_FWD_CH1 | F_CRS_DATA_STORE_N_FWD_CH0, + "CRS store and forward FIFO ECC error" }, + { F_TRACE_FWD_FIFO_CERR_CH3 | F_TRACE_FWD_FIFO_CERR_CH2 | + F_TRACE_FWD_FIFO_CERR_CH1 | F_TRACE_FWD_FIFO_CERR_CH0, + "Trace packet forward FIFO ECC error" }, + { F_TRANSPARENT_ENCAP_FWD_FIFO_CERR_CH3 | F_TRANSPARENT_ENCAP_FWD_FIFO_CERR_CH2 | + F_TRANSPARENT_ENCAP_FWD_FIFO_CERR_CH1 | F_TRANSPARENT_ENCAP_FWD_FIFO_CERR_CH0, + "Transparent encap forward FIFO ECC error" }, + { F_PTP_TRACE_FWD_FIFO_CERR_CH3 | F_PTP_TRACE_FWD_FIFO_CERR_CH2 | + F_PTP_TRACE_FWD_FIFO_CERR_CH1 | F_PTP_TRACE_FWD_FIFO_CERR_CH0, + "PTP packet forward FIFO ECC error" }, + { 0 } + }; static const struct intr_info mps_rx_perr_intr_info4 = { .name = "MPS_RX_PERR_INT_CAUSE4", .cause_reg = A_MPS_RX_PERR_INT_CAUSE4, .enable_reg = A_MPS_RX_PERR_INT_ENABLE4, .fatal = 0xffffffff, .flags = IHF_FATAL_IFF_ENABLED, - .details = NULL, + .details = mpsrx_int_cause_4_details, .actions = NULL, }; + static const struct intr_details mpsrx_int_cause_5_details[] = { + { F_MPS2CRYP_RX_FIFO3_PERR | F_MPS2CRYP_RX_FIFO2_PERR | + F_MPS2CRYP_RX_FIFO1_PERR | F_MPS2CRYP_RX_FIFO0_PERR, + "MPS to Crypto RX interface FIFO parity error" }, + { F_VNI_MULTICAST_SRAM2_PERR | F_VNI_MULTICAST_SRAM1_PERR | + F_VNI_MULTICAST_SRAM0_PERR, + "VNI multicast SRAM parity error" }, + { F_MAC_MULTICAST_SRAM4_PERR | F_MAC_MULTICAST_SRAM3_PERR | + F_MAC_MULTICAST_SRAM2_PERR | F_MAC_MULTICAST_SRAM1_PERR | + F_MAC_MULTICAST_SRAM0_PERR, + "MAC multicast SRAM parity error" }, + { F_MEM_WRAP_IPSEC_HDR_UPD_FIFO3_PERR | F_MEM_WRAP_IPSEC_HDR_UPD_FIFO2_PERR | + F_MEM_WRAP_IPSEC_HDR_UPD_FIFO1_PERR | F_MEM_WRAP_IPSEC_HDR_UPD_FIFO0_PERR, + "IPsec header update storing FIFO parity error" }, + { F_MEM_WRAP_CR2MPS_RX_FIFO3_PERR | F_MEM_WRAP_CR2MPS_RX_FIFO2_PERR | + F_MEM_WRAP_CR2MPS_RX_FIFO1_PERR | F_MEM_WRAP_CR2MPS_RX_FIFO0_PERR, + "IPsec storing FIFO parity error" }, + { F_MEM_WRAP_NON_IPSEC_FIFO3_PERR | F_MEM_WRAP_NON_IPSEC_FIFO2_PERR | + F_MEM_WRAP_NON_IPSEC_FIFO1_PERR | F_MEM_WRAP_NON_IPSEC_FIFO0_PERR, + "Non-IPsec storing FIFO parity error" }, + { F_MEM_WRAP_TP_DB_REQ_FIFO3_PERR | F_MEM_WRAP_TP_DB_REQ_FIFO2_PERR | + F_MEM_WRAP_TP_DB_REQ_FIFO1_PERR | F_MEM_WRAP_TP_DB_REQ_FIFO0_PERR, + "TP DB request storing FIFO parity error" }, + { F_MEM_WRAP_CNTRL_FIFO3_PERR | F_MEM_WRAP_CNTRL_FIFO2_PERR | + F_MEM_WRAP_CNTRL_FIFO1_PERR | F_MEM_WRAP_CNTRL_FIFO0_PERR, + "Header flit storing FIFO parity error" }, + { 0 } + }; static const struct intr_info mps_rx_perr_intr_info5 = { .name = "MPS_RX_PERR_INT_CAUSE5", .cause_reg = A_MPS_RX_PERR_INT_CAUSE5, .enable_reg = A_MPS_RX_PERR_INT_ENABLE5, .fatal = 0xffffffff, .flags = IHF_FATAL_IFF_ENABLED, - .details = NULL, + .details = mpsrx_int_cause_5_details, .actions = NULL, }; + static const struct intr_details mpsrx_int_cause_6_details[] = { + { F_T7_MEM_WRAP_IPSEC_HDR_UPD_FIFO3_PERR | F_T7_MEM_WRAP_IPSEC_HDR_UPD_FIFO2_PERR | + F_T7_MEM_WRAP_IPSEC_HDR_UPD_FIFO1_PERR | F_T7_MEM_WRAP_IPSEC_HDR_UPD_FIFO0_PERR, + "IPsec header update storing FIFO parity error" }, + { F_MEM_WRAP_CR2MPS_UPDTD_HDR_FIFO3_PERR | F_MEM_WRAP_CR2MPS_UPDTD_HDR_FIFO2_PERR | + F_MEM_WRAP_CR2MPS_UPDTD_HDR_FIFO1_PERR | F_MEM_WRAP_CR2MPS_UPDTD_HDR_FIFO0_PERR, + "IPsec updated header only storing FIFO parity error" }, + { F_MEM_WRAP_CR2MPS_RX_FIFO3_PERR | F_MEM_WRAP_CR2MPS_RX_FIFO2_PERR | + F_MEM_WRAP_CR2MPS_RX_FIFO1_PERR | F_MEM_WRAP_CR2MPS_RX_FIFO0_PERR, + "IPsec storing FIFO parity error" }, + { F_MEM_WRAP_NON_IPSEC_FIFO3_PERR | F_MEM_WRAP_NON_IPSEC_FIFO2_PERR | + F_MEM_WRAP_NON_IPSEC_FIFO1_PERR | F_MEM_WRAP_NON_IPSEC_FIFO0_PERR, + "Non-IPsec storing FIFO parity error" }, + { F_MEM_WRAP_TP_DB_REQ_FIFO3_PERR | F_MEM_WRAP_TP_DB_REQ_FIFO2_PERR | + F_MEM_WRAP_TP_DB_REQ_FIFO1_PERR | F_MEM_WRAP_TP_DB_REQ_FIFO0_PERR, + "TP DB request storing FIFO parity error" }, + { F_MEM_WRAP_CNTRL_FIFO3_PERR | F_MEM_WRAP_CNTRL_FIFO2_PERR | + F_MEM_WRAP_CNTRL_FIFO1_PERR | F_MEM_WRAP_CNTRL_FIFO0_PERR, + "Header flit storing FIFO parity error" }, + { 0 } + }; static const struct intr_info mps_rx_perr_intr_info6 = { .name = "MPS_RX_PERR_INT_CAUSE6", .cause_reg = A_MPS_RX_PERR_INT_CAUSE6, .enable_reg = A_MPS_RX_PERR_INT_ENABLE6, .fatal = 0xffffffff, .flags = IHF_FATAL_IFF_ENABLED, - .details = NULL, + .details = mpsrx_int_cause_6_details, .actions = NULL, }; + static const struct intr_details t7_mpstx_int_cause_details[] = { + { F_T7_PORTERR, "Tx received a frame for TP destined to a disable port" }, + { F_T7_FRMERR, "Framing error in received Data from TP or Data to MAC" }, + { F_T7_SECNTERR, "SOP-EOP count error in received Data from TP or Data to MAC" }, + { F_T7_BUBBLE, "Valid is deasserted between SOP and EOP" }, + { F_TX_TF_FIFO_PERR, "Parity error of TX token fifo" }, + { F_TX_FIFO_PERR, "Parity error of TX MPS2MAC underrun fifo" }, + { 0x0003c000, "Parity error of fifo storing non-ipsec +1 flit ipsec pkt" }, + { 0x00003fc0, "Interface parity error on TP/Crypto to MPS TX" }, + { F_NCSI2MPS, "interface Parity Error on ncsi2mps_tx_ch3" }, + { F_NCSIFIFO, "Parity Error in mps_tx_arbiter input FIFO (from NCSI)" }, + { 0x0000000f, "Parity Error in mps_tx_arbiter input FIFO (from TP)" }, + { 0 } + }; static const struct intr_details mps_tx_intr_details[] = { { F_PORTERR, "MPS Tx destination port is disabled" }, { F_FRMERR, "MPS Tx framing error" }, @@ -5921,22 +7118,27 @@ static bool mps_intr_handler(struct adapter *adap, int arg, int flags) { V_TPFIFO(M_TPFIFO), "MPS Tx TP FIFO parity error" }, { 0 } }; - static const struct intr_info mps_tx_intr_info = { + struct intr_info mps_tx_intr_info = { .name = "MPS_TX_INT_CAUSE", .cause_reg = A_MPS_TX_INT_CAUSE, .enable_reg = A_MPS_TX_INT_ENABLE, .fatal = 0x1ffff, .flags = IHF_FATAL_IFF_ENABLED, - .details = mps_tx_intr_details, + .details = NULL, .actions = NULL, }; + static const struct intr_details mpstx_int_cause_2_details[] = { + { F_TX_FIFO_PERR, "ECC error of TX MPS2MAC underrun fifo" }, + { 0x0000000f, "ECC error of fifo storing non-ipsec +1 flit ipsec pkt" }, + { 0 } + }; static const struct intr_info mps_tx_intr_info2 = { .name = "MPS_TX_INT2_CAUSE", .cause_reg = A_MPS_TX_INT2_CAUSE, .enable_reg = A_MPS_TX_INT2_ENABLE, .fatal = 0xffffffff, .flags = IHF_FATAL_IFF_ENABLED, - .details = NULL, + .details = mpstx_int_cause_2_details, .actions = NULL, }; static const struct intr_info mps_tx_intr_info3 = { @@ -5972,22 +7174,51 @@ static bool mps_intr_handler(struct adapter *adap, int arg, int flags) .details = mps_trc_intr_details, .actions = NULL, }; + static const struct intr_details t7_mps_trc_intr_details[] = { + { F_T7_TRCPLERRENB, "TRC PL error" }, + { F_T7_MISCPERR, "TRC header register parity error" }, + { 0x0000ff00, "TRC packet FIFO parity error" }, + { 0x000000ff, "TRC filter memory parity error" }, + { 0 } + }; static const struct intr_info t7_mps_trc_intr_info = { .name = "MPS_TRC_INT_CAUSE", .cause_reg = A_T7_MPS_TRC_INT_CAUSE, .enable_reg = A_T7_MPS_TRC_INT_ENABLE, .fatal = 0xffffffff, .flags = IHF_FATAL_IFF_ENABLED, - .details = mps_trc_intr_details, + .details = t7_mps_trc_intr_details, .actions = NULL, }; + static const struct intr_details t7_trc_int_cause2_details[] = { + { 0x0001e000, "TRC Tx2Rx down-converter correctable error" }, + { 0x00001800, "TRC MPS2MAC down-converter correctable error" }, + { 0x00000600, "TRC MAC2MPS down-converter correctable error" }, + { 0x000001e0, "TRC Tx2Rx down-converter parity error" }, + { 0x00000018, "TRC MAC2MPS down-converter parity error" }, + { 0x00000006, "TRC MPS2MAC down-converter parity error" }, + { 0 } + }; static const struct intr_info t7_mps_trc_intr_info2 = { .name = "MPS_TRC_INT_CAUSE2", .cause_reg = A_MPS_TRC_INT_CAUSE2, .enable_reg = A_MPS_TRC_INT_ENABLE2, .fatal = 0xffffffff, .flags = IHF_FATAL_IFF_ENABLED, - .details = NULL, + .details = t7_trc_int_cause2_details, + .actions = NULL, + }; + static const struct intr_details mps_stat_intr_details[] = { + { F_PLREADSYNCERR, "MPS pl read sync error" }, + { 0 } + }; + static const struct intr_info mps_stat_intr_info = { + .name = "MPS_STAT_INT_CAUSE", + .cause_reg = A_MPS_STAT_INT_CAUSE, + .enable_reg = A_MPS_STAT_INT_ENABLE, + .fatal = 0xf, + .flags = IHF_FATAL_IFF_ENABLED, + .details = mps_stat_intr_details, .actions = NULL, }; static const struct intr_details mps_stat_sram_intr_details[] = { @@ -6030,6 +7261,9 @@ static bool mps_intr_handler(struct adapter *adap, int arg, int flags) .actions = NULL, }; static const struct intr_details mps_cls_intr_details[] = { + { F_T7_PLERRENB, "PL error"}, + { F_CIM2MPS_INTF_PAR, "cim2mps interface parity"}, + { F_TCAM_CRC_SRAM, "tcam crc sram parity error"}, { F_HASHSRAM, "MPS hash SRAM parity error" }, { F_MATCHTCAM, "MPS match TCAM parity error" }, { F_MATCHSRAM, "MPS match SRAM parity error" }, @@ -6058,9 +7292,14 @@ static bool mps_intr_handler(struct adapter *adap, int arg, int flags) .actions = NULL, }; bool fatal = false; + if (chip_id(adap) >= CHELSIO_T7) + mps_tx_intr_info.details = t7_mpstx_int_cause_details; + else + mps_tx_intr_info.details = mps_tx_intr_details; fatal |= t4_handle_intr(adap, &mps_rx_perr_intr_info, 0, flags); if (chip_id(adap) > CHELSIO_T6) { + fatal |= t4_handle_intr(adap, &mps_rx_func_intr_info, 0, flags); fatal |= t4_handle_intr(adap, &mps_rx_perr_intr_info2, 0, flags); fatal |= t4_handle_intr(adap, &mps_rx_perr_intr_info3, 0, flags); fatal |= t4_handle_intr(adap, &mps_rx_perr_intr_info4, 0, flags); @@ -6076,6 +7315,7 @@ static bool mps_intr_handler(struct adapter *adap, int arg, int flags) fatal |= t4_handle_intr(adap, &t7_mps_trc_intr_info2, 0, flags); } else fatal |= t4_handle_intr(adap, &mps_trc_intr_info, 0, flags); + fatal |= t4_handle_intr(adap, &mps_stat_intr_info, 0, flags); fatal |= t4_handle_intr(adap, &mps_stat_sram_intr_info, 0, flags); fatal |= t4_handle_intr(adap, &mps_stat_tx_intr_info, 0, flags); fatal |= t4_handle_intr(adap, &mps_stat_rx_intr_info, 0, flags); @@ -6087,7 +7327,6 @@ static bool mps_intr_handler(struct adapter *adap, int arg, int flags) t4_read_reg(adap, A_MPS_INT_CAUSE); /* flush */ return (fatal); - } /* @@ -6096,7 +7335,7 @@ static bool mps_intr_handler(struct adapter *adap, int arg, int flags) static bool mem_intr_handler(struct adapter *adap, int idx, int flags) { static const char name[4][5] = { "EDC0", "EDC1", "MC0", "MC1" }; - unsigned int count_reg, v; + unsigned int count_reg = 0, v; static const struct intr_details mem_intr_details[] = { { F_ECC_UE_INT_CAUSE, "Uncorrectable ECC data error(s)" }, { F_ECC_CE_INT_CAUSE, "Correctable ECC data error(s)" }, @@ -6104,10 +7343,10 @@ static bool mem_intr_handler(struct adapter *adap, int idx, int flags) { 0 } }; static const struct intr_details t7_mem_intr_details[] = { - { F_DDRPHY_INT_CAUSE, "DDRPHY" }, - { F_DDRCTL_INT_CAUSE, "DDRCTL" }, - { F_T7_ECC_CE_INT_CAUSE, "Correctable ECC data error(s)" }, + { F_DDRPHY_INT_CAUSE, "DDR PHY" }, + { F_DDRCTL_INT_CAUSE, "DDR Controller" }, { F_T7_ECC_UE_INT_CAUSE, "Uncorrectable ECC data error(s)" }, + { F_T7_ECC_CE_INT_CAUSE, "Correctable ECC data error(s)" }, { F_PERR_INT_CAUSE, "FIFO parity error" }, { 0 } }; @@ -6115,8 +7354,8 @@ static bool mem_intr_handler(struct adapter *adap, int idx, int flags) struct intr_info ii = { .name = &rname[0], .fatal = F_PERR_INT_CAUSE | F_ECC_UE_INT_CAUSE, + .flags = IHF_CLR_DELAYED, .details = mem_intr_details, - .flags = 0, .actions = NULL, }; bool fatal = false; @@ -6137,15 +7376,6 @@ static bool mem_intr_handler(struct adapter *adap, int idx, int flags) count_reg = EDC_T5_REG(A_EDC_H_ECC_STATUS, i); } fatal |= t4_handle_intr(adap, &ii, 0, flags); - if (chip_id(adap) > CHELSIO_T6) { - snprintf(rname, sizeof(rname), "EDC%u_PAR_CAUSE", i); - ii.cause_reg = EDC_T5_REG(A_EDC_H_PAR_CAUSE, i); - ii.enable_reg = EDC_T5_REG(A_EDC_H_PAR_ENABLE, i); - ii.fatal = 0xffffffff; - ii.details = NULL; - ii.flags = IHF_FATAL_IFF_ENABLED; - fatal |= t4_handle_intr(adap, &ii, 0, flags); - } break; case MEM_MC1: if (is_t4(adap) || is_t6(adap)) @@ -6167,52 +7397,30 @@ static bool mem_intr_handler(struct adapter *adap, int idx, int flags) ii.enable_reg = MC_T7_REG(A_T7_MC_P_INT_ENABLE, i); ii.fatal = F_PERR_INT_CAUSE | F_T7_ECC_UE_INT_CAUSE; ii.details = t7_mem_intr_details; - count_reg = MC_T7_REG(A_T7_MC_P_ECC_STATUS, i); } fatal |= t4_handle_intr(adap, &ii, 0, flags); - - snprintf(rname, sizeof(rname), "MC%u_PAR_CAUSE", i); - if (is_t4(adap)) { - ii.cause_reg = A_MC_PAR_CAUSE; - ii.enable_reg = A_MC_PAR_ENABLE; - } else if (chip_id(adap) < CHELSIO_T7) { - ii.cause_reg = MC_REG(A_MC_P_PAR_CAUSE, i); - ii.enable_reg = MC_REG(A_MC_P_PAR_ENABLE, i); - } else { - ii.cause_reg = MC_T7_REG(A_T7_MC_P_PAR_CAUSE, i); - ii.enable_reg = MC_T7_REG(A_T7_MC_P_PAR_ENABLE, i); - } - ii.fatal = 0xffffffff; - ii.details = NULL; - ii.flags = IHF_FATAL_IFF_ENABLED; - fatal |= t4_handle_intr(adap, &ii, 0, flags); - - if (chip_id(adap) > CHELSIO_T6) { - snprintf(rname, sizeof(rname), "MC%u_DDRCTL_INT_CAUSE", i); - ii.cause_reg = MC_T7_REG(A_MC_P_DDRCTL_INT_CAUSE, i); - ii.enable_reg = MC_T7_REG(A_MC_P_DDRCTL_INT_ENABLE, i); - fatal |= t4_handle_intr(adap, &ii, 0, flags); - } break; } - v = t4_read_reg(adap, count_reg); - if (v != 0) { - if (G_ECC_UECNT(v) != 0 && !(flags & IHF_NO_SHOW)) { - CH_ALERT(adap, - " %s: %u uncorrectable ECC data error(s)\n", - name[idx], G_ECC_UECNT(v)); - } - if (G_ECC_CECNT(v) != 0 && !(flags & IHF_NO_SHOW)) { - if (idx <= MEM_EDC1) - t4_edc_err_read(adap, idx); - CH_WARN_RATELIMIT(adap, - " %s: %u correctable ECC data error(s)\n", - name[idx], G_ECC_CECNT(v)); + if (count_reg != 0) { + v = t4_read_reg(adap, count_reg); + if (v != 0) { + if (G_ECC_UECNT(v) != 0 && !(flags & IHF_NO_SHOW)) { + CH_ALERT(adap, + " %s: %u uncorrectable ECC data error(s)\n", + name[idx], G_ECC_UECNT(v)); + } + if (G_ECC_CECNT(v) != 0 && !(flags & IHF_NO_SHOW)) { + if (idx <= MEM_EDC1) + t4_edc_err_read(adap, idx); + CH_WARN_RATELIMIT(adap, + " %s: %u correctable ECC data error(s)\n", + name[idx], G_ECC_CECNT(v)); + } + t4_write_reg(adap, count_reg, 0xffffffff); } - t4_write_reg(adap, count_reg, 0xffffffff); } - + clear_int_cause_reg(adap, &ii, flags); return (fatal); } @@ -6231,14 +7439,13 @@ static bool ma_wrap_status(struct adapter *adap, int arg, int flags) return (false); } - /* * MA interrupt handler. */ static bool ma_intr_handler(struct adapter *adap, int arg, int flags) { static const struct intr_action ma_intr_actions[] = { - { F_MEM_WRAP_INT_CAUSE, 0, ma_wrap_status }, + { F_MEM_WRAP_INT_CAUSE, -1, ma_wrap_status }, { 0 }, }; static const struct intr_info ma_intr_info = { @@ -6284,10 +7491,29 @@ static bool ma_intr_handler(struct adapter *adap, int arg, int flags) */ static bool smb_intr_handler(struct adapter *adap, int arg, int flags) { - static const struct intr_details smb_int_cause_fields[] = { - { F_MSTTXFIFOPARINT, "SMB master Tx FIFO parity error" }, - { F_MSTRXFIFOPARINT, "SMB master Rx FIFO parity error" }, - { F_SLVFIFOPARINT, "SMB slave FIFO parity error" }, + static const struct intr_details smb_int_cause_details[] = { + { F_MSTTXFIFOPARINT, "Master has Parity Error in Tx Fifo" }, + { F_MSTRXFIFOPARINT, "Master has Parity Error in Rx Fifo" }, + { F_SLVFIFOPARINT, "Slave has Parity Error in Fifo" }, + { F_SLVUNEXPBUSSTOPINT, "Slave get Unexpected BusStop" }, + { F_SLVUNEXPBUSSTARTINT, "Slave get Unexpected BusStart" }, + { F_SLVCOMMANDCODEINVINT, "Slave get Invalid Command Code" }, + { F_SLVBYTECNTERRINT, "Slave get Erroneous ByteCount value" }, + { F_SLVUNEXPACKMSTINT, "Slave get Unexpected Ack from Master" }, + { F_SLVUNEXPNACKMSTINT, "Slave get Unexpected Nack from Master" }, + { F_SLVNOBUSSTOPINT, "Slave did not get Bus Stop" }, + { F_SLVNOREPSTARTINT, "Slave has no Repeated Start" }, + { F_SLVRXADDRINT, "Slave has Address Error" }, + { F_SLVRXPECERRINT, "Slave has Pec Error" }, + { F_SLVPREPTOARPINT, "PL has invalid request" }, + { F_SLVTIMEOUTINT, "Slave has timed out" }, + { F_SLVERRINT, "Slave detected error during the current transfer" }, + { F_SLVDONEINT, "Slave has completed the current transaction" }, + { F_SLVRXRDYINT, "Slave has received bytes to be processed by uP" }, + { F_MSTTIMEOUTINT, "Master has timed out" }, + { F_MSTNACKINT, "Master has detected a NAck on the transfer" }, + { F_MSTLOSTARBINT, "Master has lost arbitration all the timeline" }, + { F_MSTDONEINT, "Master has completed the current transaction" }, { 0 } }; static const struct intr_info smb_int_cause = { @@ -6296,9 +7522,10 @@ static bool smb_intr_handler(struct adapter *adap, int arg, int flags) .enable_reg = A_SMB_INT_ENABLE, .fatal = F_SLVFIFOPARINT | F_MSTRXFIFOPARINT | F_MSTTXFIFOPARINT, .flags = 0, - .details = smb_int_cause_fields, + .details = smb_int_cause_details, .actions = NULL, }; + return (t4_handle_intr(adap, &smb_int_cause, 0, flags)); } @@ -6308,6 +7535,7 @@ static bool smb_intr_handler(struct adapter *adap, int arg, int flags) static bool ncsi_intr_handler(struct adapter *adap, int arg, int flags) { static const struct intr_details ncsi_int_cause_fields[] = { + { F_CIM2NC_PERR, " CIM to NC parity error" }, { F_CIM_DM_PRTY_ERR, "NC-SI CIM parity error" }, { F_MPS_DM_PRTY_ERR, "NC-SI MPS parity error" }, { F_TXFIFO_PRTY_ERR, "NC-SI Tx FIFO parity error" }, @@ -6324,13 +7552,31 @@ static bool ncsi_intr_handler(struct adapter *adap, int arg, int flags) .details = ncsi_int_cause_fields, .actions = NULL, }; + static const struct intr_details ncsi_xgmac0_int_cause_details[] = { + { F_XAUIPCSDECERR, "RGMII PCS DEC Error" }, + { F_RGMIIRXFIFOOVERFLOW, "RGMII receive FIFO over flow" }, + { F_RGMIIRXFIFOUNDERFLOW, "RGMII receive FIFO under flow" }, + { F_RXPKTSIZEERROR, "Receive over size packet" }, + { F_WOLPATDETECTED, "WOL pattern detected" }, + { 0x000e0000, "Tx FIFO parity error" }, + { 0x0001c000, "Rx FIFO parity error" }, + { F_TXFIFO_UNDERRUN, "Tx FIFO underrun" }, + { F_RXFIFO_OVERFLOW, "Rx FIFO overflow" }, + { 0x00000f00, "XAUI SERDES BIST error" }, + { 0x000000f0, "XAUI SERDES receive low signal change" }, + { F_XAUIPCSCTCERR, "XAUI PCS CTC FIFO error" }, + { F_XAUIPCSALIGNCHANGE, "XAUI PCS alignment change" }, + { F_RGMIILINKSTSCHANGE, "RGMII link status change" }, + { F_XGM_INT, "XGM Core embedded interrupt (2nd level)" }, + { 0 } + }; static const struct intr_info ncsi_xgmac0_int_cause = { .name = "NCSI_XGMAC0_INT_CAUSE", .cause_reg = A_NCSI_XGMAC0_INT_CAUSE, .enable_reg = A_NCSI_XGMAC0_INT_ENABLE, .fatal = 0, .flags = 0, - .details = NULL, + .details = ncsi_xgmac0_int_cause_details, .actions = NULL, }; bool fatal = false; @@ -6346,32 +7592,71 @@ static bool ncsi_intr_handler(struct adapter *adap, int arg, int flags) */ static bool mac_intr_handler(struct adapter *adap, int port, int flags) { + static const struct intr_details mac_int_cause_cmn_details[] = { + { 0x3fffc0, "HSS PLL lock error " }, + { F_FLOCK_ASSERTED, "frequency lock coming out of DPLL sub-block is asserted" }, + { F_FLOCK_LOST, "frequency lock coming out of DPLL sub-blocki is lost." }, + { F_PHASE_LOCK_ASSERTED, "PHASE LOCK from DPLL sub-block is asserted" }, + { F_PHASE_LOCK_LOST, "PHASE LOCK from DPLL sub-block is lost." }, + { F_LOCK_ASSERTED, "Lock from frac_n PLL inside t7_clk module is asserted" }, + { F_LOCK_LOST, "Lock from frac_n PLL inside t7_clk module is lost " }, + { 0 } + }; static const struct intr_info mac_int_cause_cmn = { .name = "MAC_INT_CAUSE_CMN", .cause_reg = A_MAC_INT_CAUSE_CMN, .enable_reg = A_MAC_INT_EN_CMN, .fatal = 0, .flags = 0, - .details = NULL, + .details = mac_int_cause_cmn_details, .actions = NULL, }; + static const struct intr_details mac_perr_int_cause_mtip_details[] = { + { F_PERR_MAC0_TX, "MTIP MAC TX memory for MAC 0 (the 200G MAC for port 0)" }, + { F_PERR_MAC1_TX, "MTIP MAC TX memory for MAC 1 (the 200G MAC for port 1)" }, + { F_PERR_MAC2_TX, "MTIP MAC TX memory for MAC 2 (the 10-100G MAC for port 0)" }, + { F_PERR_MAC3_TX, "MTIP MAC TX memory for MAC 3 (the 10-100G MAC for port 1)" }, + { F_PERR_MAC4_TX, "MTIP MAC TX memory for MAC 4 (the 10-100G MAC for port 2)" }, + { F_PERR_MAC5_TX, "MTIP MAC TX memory for MAC 5 (the 10-100G MAC for port 3)" }, + { F_PERR_MAC0_RX, "MTIP MAC RX memory for MAC 0 (the 200G MAC for port 0)" }, + { F_PERR_MAC1_RX, "MTIP MAC RX memory for MAC 1 (the 200G MAC for port 1)" }, + { F_PERR_MAC2_RX, "MTIP MAC RX memory for MAC 2 (the 10-100G MAC for port 0)" }, + { F_PERR_MAC3_RX, "MTIP MAC RX memory for MAC 3 (the 10-100G MAC for port 1)" }, + { F_PERR_MAC4_RX, "MTIP MAC RX memory for MAC 4 (the 10-100G MAC for port 2)" }, + { F_PERR_MAC5_RX, "MTIP MAC RX memory for MAC 5 (the 10-100G MAC for port 3)" }, + { F_PERR_MAC_STAT_RX, "MTIP MAC RX statistics memory (1 for all 4 10-100G MACs)" }, + { F_PERR_MAC_STAT_TX, "MTIP MAC TX statistics memory (1 for all 4 10-100G MACs)" }, + { F_PERR_MAC_STAT_CAP, "MTIP MAC stat capture memory (1 for all 4 100G MACs)" }, + { 0 } + }; static const struct intr_info mac_perr_cause_mtip = { .name = "MAC_PERR_INT_CAUSE_MTIP", .cause_reg = A_MAC_PERR_INT_CAUSE_MTIP, .enable_reg = A_MAC_PERR_INT_EN_MTIP, .fatal = 0xffffffff, .flags = IHF_FATAL_IFF_ENABLED | IHF_IGNORE_IF_DISABLED, - .details = NULL, + .details = mac_perr_int_cause_mtip_details, .actions = NULL, }; - static const struct intr_info mac_cerr_cause_mtip = { - .name = "MAC_CERR_INT_CAUSE_MTIP", - .cause_reg = A_MAC_CERR_INT_CAUSE_MTIP, - .enable_reg = A_MAC_CERR_INT_EN_MTIP, - .fatal = 0, - .flags = 0, - .details = NULL, - .actions = NULL, + static const struct intr_details ios_intr_cause_quad0_details[] = { + { F_Q0_MAILBOX_INT_ASSERT, "Etopus Quad0 Mailbox interrupt cause" }, + { 0x00f00000, "Etopus Quad0 training failure" }, + { 0x000f0000, "Etopus Quad0 training complete" }, + { 0x0000f000, "Etopus Quad0 AN TX interrupt" }, + { 0x00000f00, "Etopus Quad0 signal detect assertion" }, + { 0x000000f0, "Etopus Quad0 CDR LOL assertion" }, + { 0x0000000f, "Etopus Quad0 LOS signal assertion" }, + { 0 } + }; + static const struct intr_details ios_intr_cause_quad1_details[] = { + { F_Q1_MAILBOX_INT_ASSERT, "Etopus Quad1 Mailbox interrupt cause" }, + { 0x00f00000, "Etopus Quad1 training failure" }, + { 0x000f0000, "Etopus Quad1 training complete" }, + { 0x0000f000, "Etopus Quad1 AN TX interrupt" }, + { 0x00000f00, "Etopus Quad1 signal detect assertion" }, + { 0x000000f0, "Etopus Quad1 CDR LOL assertion" }, + { 0x0000000f, "Etopus Quad1 LOS signal assertion" }, + { 0 } }; static const struct intr_info mac_ios_int_cause_quad0 = { .name = "MAC_IOS_INTR_CAUSE_QUAD0", @@ -6379,7 +7664,7 @@ static bool mac_intr_handler(struct adapter *adap, int port, int flags) .enable_reg = A_MAC_IOS_INTR_EN_QUAD0, .fatal = 0, .flags = 0, - .details = NULL, + .details = ios_intr_cause_quad0_details, .actions = NULL, }; static const struct intr_info mac_ios_int_cause_quad1 = { @@ -6388,7 +7673,7 @@ static bool mac_intr_handler(struct adapter *adap, int port, int flags) .enable_reg = A_MAC_IOS_INTR_EN_QUAD1, .fatal = 0, .flags = 0, - .details = NULL, + .details = ios_intr_cause_quad1_details, .actions = NULL, }; static const struct intr_details mac_intr_details[] = { @@ -6396,6 +7681,33 @@ static bool mac_intr_handler(struct adapter *adap, int port, int flags) { F_RXFIFO_PRTY_ERR, "MAC Rx FIFO parity error" }, { 0 } }; + static const struct intr_details t7_mac_int_cause_details[] = { + { F_MAC2MPS_PERR_CAUSE, "MPS2MAC Data parity error per port" }, + { F_MAC_PPS_INT_CAUSE, "One second interrupt based on PTP timer" }, + { F_MAC_TX_TS_AVAIL_INT_CAUSE, + "Time stamp is available for the last IEEE 1588 event frame" }, + { F_MAC_PATDETWAKE_INT_CAUSE, "Wake up pattern match packet received" }, + { F_MAC_MAGIC_WAKE_INT_CAUSE, "Magic packet received" }, + { F_MAC_SIGDETCHG_INT_CAUSE, "Signal Detect Change" }, + { F_MAC_PCS_LINK_GOOD_CAUSE, "PCS link good (xaui pcsr or 1g)" }, + { F_MAC_PCS_LINK_FAIL_CAUSE, "PCS Failure (xaui pcsr or 1g)" }, + { F_RXFIFOOVERFLOW, "RX Fifo Over flow error" }, + { F_MAC_REM_FAULT_INT_CAUSE, "Remote fault received by XGMAC" }, + { F_MAC_LOC_FAULT_INT_CAUSE, "Local fault received by XGMAC" }, + { F_MAC_LINK_DOWN_INT_CAUSE, "Link is down" }, + { F_MAC_LINK_UP_INT_CAUSE, "Link is up" }, + { F_MAC_AN_DONE_INT_CAUSE, "Autonegotiation complete" }, + { F_MAC_AN_PGRD_INT_CAUSE, "An page received" }, + { F_MAC_TXFIFO_ERR_INT_CAUSE, "Tx FIFO parity error" }, + { F_MAC_RXFIFO_ERR_INT_CAUSE, "Rx FIFO parity error" }, + { 0 } + }; + static const struct intr_details mac_perr_int_cause_details[] = { + { F_T6_PERR_PKT_RAM, "WoL packet data memory" }, + { F_T6_PERR_MASK_RAM, "WoL mask memory" }, + { F_T6_PERR_CRC_RAM, "WoL CRC memory" }, + { 0 } + }; char name[32]; struct intr_info ii; bool fatal = false; @@ -6428,7 +7740,7 @@ static bool mac_intr_handler(struct adapter *adap, int port, int flags) ii.enable_reg = T7_PORT_REG(port, A_T7_MAC_PORT_INT_EN); ii.fatal = 0xffffffff; ii.flags = IHF_FATAL_IFF_ENABLED; - ii.details = NULL; + ii.details = t7_mac_int_cause_details; ii.actions = NULL; } fatal |= t4_handle_intr(adap, &ii, 0, flags); @@ -6443,7 +7755,7 @@ static bool mac_intr_handler(struct adapter *adap, int port, int flags) ii.enable_reg = T7_PORT_REG(port, A_T7_MAC_PORT_PERR_INT_EN); ii.fatal = 0xffffffff; ii.flags = IHF_FATAL_IFF_ENABLED; - ii.details = NULL; + ii.details = mac_perr_int_cause_details; ii.actions = NULL; } else { ii.name = &name[0]; @@ -6484,7 +7796,6 @@ static bool mac_intr_handler(struct adapter *adap, int port, int flags) MPASS(chip_id(adap) >= CHELSIO_T7); fatal |= t4_handle_intr(adap, &mac_int_cause_cmn, 0, flags); fatal |= t4_handle_intr(adap, &mac_perr_cause_mtip, 0, flags); - fatal |= t4_handle_intr(adap, &mac_cerr_cause_mtip, 0, flags); fatal |= t4_handle_intr(adap, &mac_ios_int_cause_quad0, 0, flags); fatal |= t4_handle_intr(adap, &mac_ios_int_cause_quad1, 0, flags); @@ -6506,28 +7817,40 @@ static bool pl_timeout_status(struct adapter *adap, int arg, int flags) static bool plpl_intr_handler(struct adapter *adap, int arg, int flags) { static const struct intr_details plpl_int_cause_fields[] = { + { F_FATALPERR, "Fatal parity error" }, + { F_PERRVFID, "VFID_MAP parity error" }, + { 0 } + }; + static const struct intr_details t5_plpl_int_cause_fields[] = { { F_PL_BUSPERR, "Bus parity error" }, { F_FATALPERR, "Fatal parity error" }, { F_INVALIDACCESS, "Global reserved memory access" }, { F_TIMEOUT, "Bus timeout" }, { F_PLERR, "Module reserved access" }, - { F_PERRVFID, "VFID_MAP parity error" }, { 0 } }; static const struct intr_action plpl_int_cause_actions[] = { { F_TIMEOUT, -1, pl_timeout_status }, { 0 }, }; - static const struct intr_info plpl_int_cause = { + struct intr_info plpl_int_cause = { .name = "PL_PL_INT_CAUSE", .cause_reg = A_PL_PL_INT_CAUSE, .enable_reg = A_PL_PL_INT_ENABLE, - .fatal = F_FATALPERR | F_PERRVFID, - .flags = IHF_FATAL_IFF_ENABLED | IHF_IGNORE_IF_DISABLED, - .details = plpl_int_cause_fields, - .actions = plpl_int_cause_actions, + .fatal = F_FATALPERR, + .flags = IHF_FATAL_IFF_ENABLED, + .details = NULL, + .actions = NULL, }; + if (is_t4(adap)) { + plpl_int_cause.fatal |= F_PERRVFID; + plpl_int_cause.details = plpl_int_cause_fields; + } else { + plpl_int_cause.fatal |= F_INVALIDACCESS; + plpl_int_cause.details = t5_plpl_int_cause_fields; + plpl_int_cause.actions = plpl_int_cause_actions; + } return (t4_handle_intr(adap, &plpl_int_cause, 0, flags)); } @@ -6587,7 +7910,7 @@ static bool hma_intr_handler(struct adapter *adap, int idx, int flags) { F_RTF_INT_CAUSE, "Region translation fault" }, { F_PCIEMST_INT_CAUSE, "PCIe master access error" }, { F_MAMST_INT_CAUSE, "MA master access error" }, - { 1, "FIFO parity error" }, + { F_PERR_INT_CAUSE, "FIFO parity error" }, { 0 } }; static const struct intr_info hma_int_cause = { @@ -6682,15 +8005,6 @@ static bool gcache_intr_handler(struct adapter *adap, int idx, int flags) { F_ILLADDRACCESS0_INT_CAUSE, "GC0 illegal address access" }, { 0 } }; - static const struct intr_info gcache_perr_cause = { - .name = "GCACHE_PAR_CAUSE", - .cause_reg = A_GCACHE_PAR_CAUSE, - .enable_reg = A_GCACHE_PAR_ENABLE, - .fatal = 0xffffffff, - .flags = IHF_FATAL_IFF_ENABLED, - .details = NULL, - .actions = NULL, - }; static const struct intr_info gcache_int_cause = { .name = "GCACHE_INT_CAUSE", .cause_reg = A_GCACHE_INT_CAUSE, @@ -6700,12 +8014,7 @@ static bool gcache_intr_handler(struct adapter *adap, int idx, int flags) .details = gcache_int_cause_fields, .actions = NULL, }; - bool fatal = false; - - fatal |= t4_handle_intr(adap, &gcache_int_cause, 0, flags); - fatal |= t4_handle_intr(adap, &gcache_perr_cause, 0, flags); - - return (fatal); + return (t4_handle_intr(adap, &gcache_int_cause, 0, flags)); } /* @@ -6713,67 +8022,218 @@ static bool gcache_intr_handler(struct adapter *adap, int idx, int flags) */ static bool arm_intr_handler(struct adapter *adap, int idx, int flags) { + static const struct intr_details arm_perr_int_cause0_details[] = { + { F_INIC_WRDATA_FIFO_PERR, "INT CAUSE for INIC Write Data Fifo Parity Error" }, + { F_INIC_RDATA_FIFO_PERR, "INT CAUSE for INIC Read Data Fifo Parity Error" }, + { F_MSI_MEM_PERR, "INT CAUSE for MSI Memory Parity Error" }, + { 0x18000000, "INT CAUSE for ARM Doorbell SRAM Parity Error" }, + { F_EMMC_FIFOPARINT, "INT CAUSE for EMMC Fifo Parity Interrupt" }, + { F_ICB_RAM_PERR, "INT CAUSE for ICB SRAM Parity Error" }, + { F_MESS2AXI4_WRFIFO_PERR, "INT CAUSE for Message2AXI4 Write FIFO Parity Error" }, + { F_RC_WFIFO_OUTPERR, "INT CAUSE for AXI2RC Write FIFO Parity Error" }, + { 0x00600000, "INT CAUSE for AXI2RC SRAM Parity Error" }, + { F_MSI_FIFO_PAR_ERR, "INT CAUSE for APB2MSI FIFO Parity Error" }, + { F_INIC2MA_INTFPERR, "INT CAUSE for INIC to MA Interface Parity Error" }, + { F_RDATAFIFO0_PERR, "INT CAUSE for AXI2MA M0 Read Data Fifo Parity Error" }, + { F_RDATAFIFO1_PERR, "INT CAUSE for AXI2MA M1 Read Data Fifo Parity Error" }, + { F_WRDATAFIFO0_PERR, "INT CAUSE for AXI2MA M0 Write Data Fifo Parity Error" }, + { F_WRDATAFIFO1_PERR, "INT CAUSE for AXI2MA M1 Write Data Fifo Parity Error" }, + { F_WR512DATAFIFO0_PERR, + "INT CAUSE for AXI2MA M0 Write Data 512b Fifo Parity Error" }, + { F_WR512DATAFIFO1_PERR, + "INT CAUSE for AXI2MA M1 Write Data 512b Fifo Parity Error" }, + { F_ROBUFF_PARERR3, "INT CAUSE for Reorder Buffer Parity Error" }, + { F_ROBUFF_PARERR2, "INT CAUSE for Reorder Buffer Parity Error" }, + { F_ROBUFF_PARERR1, "INT CAUSE for Reorder Buffer Parity Error" }, + { F_ROBUFF_PARERR0, "INT CAUSE for Reorder Buffer Parity Error" }, + { F_MA2AXI_REQDATAPARERR, "INT CAUSE for MA2AXI Request Data Parity Error" }, + { F_MA2AXI_REQCTLPARERR, "INT CAUSE for MA2AXI Request Control Parity Error" }, + { F_MA_RSPPERR, "INT CAUSE for MA Response Parity Error" }, + { F_PCIE2MA_REQCTLPARERR, "INT CAUSE for PCIe to MA Control Parity Error" }, + { F_PCIE2MA_REQDATAPARERR, "INT CAUSE for PCIe to MA Data Parity Error" }, + { F_INIC2MA_REQCTLPARERR, "INT CAUSE for INIC to MA Control Parity Error" }, + { F_INIC2MA_REQDATAPARERR, "INT CAUSE for INIC to MA Data Parity Error" }, + { F_MA_RSPUE, "INT CAUSE for MA Response Uncorrectable Error" }, + { F_APB2PL_RSPDATAPERR, "INT CAUSE for APB2PL Response Data Parity Error" }, + { 0 } + }; static const struct intr_info arm_perr_cause0 = { .name = "ARM_PERR_INT_CAUSE0", .cause_reg = A_ARM_PERR_INT_CAUSE0, .enable_reg = A_ARM_PERR_INT_ENB0, .fatal = 0xffffffff, .flags = IHF_IGNORE_IF_DISABLED | IHF_FATAL_IFF_ENABLED, - .details = NULL, + .details = arm_perr_int_cause0_details, .actions = NULL, }; + static const struct intr_details arm_perr_int_cause1_details[] = { + { F_ARWFIFO0_PERR, "AXI2MA M0 Read-Write FIFO Parity Error" }, + { F_ARWFIFO1_PERR, "AXI2MA M1 Read-Write FIFO Parity Error" }, + { F_ARWIDFIFO0_PERR, "AXI2MA M0 Read-Write ID FIFO Parity Error" }, + { F_ARWIDFIFO1_PERR, "AXI2MA M1 Read-Write ID FIFO Parity Error" }, + { F_ARIDFIFO0_PERR, "AXI2MA M0 Read FIFO Parity Error" }, + { F_ARIDFIFO1_PERR, "AXI2MA M1 Read FIFO Parity Error" }, + { F_RRSPADDR_FIFO0_PERR, "AXI2MA M0 Read Response Address FIFO Parity Error" }, + { F_RRSPADDR_FIFO1_PERR, "AXI2MA M1 Read Response Address FIFO Parity Error" }, + { F_WRSTRB_FIFO0_PERR, "AXI2MA M0 Write Strobe FIFO Parity Error" }, + { F_WRSTRB_FIFO1_PERR, "AXI2MA M1 Write Strobe FIFO Parity Error" }, + { F_MA2AXI_RSPDATAPARERR, "MA2AXI Response FIFO Parity Error" }, + { F_MA2AXI_DATA_PAR_ERR, "MA2AXI Write Data FIFO Parity Error" }, + { F_MA2AXI_WR_ORD_FIFO_PARERR, "MA2AXI Ordered Write Data FIFO Parity Error" }, + { F_NVME_DB_EMU_TRACKER_FIFO_PERR, "NVMe DB Emulation Tracker FIFO Parity Error" }, + { F_NVME_DB_EMU_QUEUE_AW_ADDR_FIFO_PERR, + "NVMe DB Emulation Queue AW Addr Parity Error" }, + { F_NVME_DB_EMU_INTERRUPT_OFFSET_FIFO_PERR, + "NVMe DB Emulation Interrupt Offset FIFO Parity Error" }, + { F_NVME_DB_EMU_ID_FIFO0_PERR, "NVMe DB Emulation ID FIFO0 Parity Error" }, + { F_NVME_DB_EMU_ID_FIFO1_PERR, "NVMe DB Emulation ID FIFO1 Parity Error" }, + { F_RC_ARWFIFO_PERR, "AXI2RC Read-Write FIFO Parity Error" }, + { F_RC_ARIDBURSTADDRFIFO_PERR, + "AXI2RC Read ID, Burst and Address FIFO Parity Error" }, + { F_RC_CFG_FIFO_PERR, "AXI2RC Config FIFO Parity Error" }, + { F_RC_RSPFIFO_PERR, "AXI2RC Response Parity Error" }, + { F_INIC_ARIDFIFO_PERR, "CCI2INIC Read ID FIFO Parity Error" }, + { F_INIC_ARWFIFO_PERR, "CCI2INIC Read-Write FIFO ontrol Parity Error" }, + { F_AXI2MA_128_RD_ADDR_SIZE_FIFO_PERR, + "AXI2MA(CCI2INIC) Read Address Size FIFO Parity Error" }, + { F_AXI2RC_128_RD_ADDR_SIZE_FIFO_PERR, + "AXI2RC Read Address Size FIFO Parity Error" }, + { F_ARM_MA_512B_RD_ADDR_SIZE_FIFO0_PERR, + "ARM_MA_512b Read Address Size FIFO0 Parity Error" }, + { F_ARM_MA_512B_RD_ADDR_SIZE_FIFO1_PERR, + "ARM_MA_512b Read Address Size FIFO1 Parity Error" }, + { F_ARM_MA_512B_ARB_FIFO_PERR, "ARM_MA_512b Arbiter FIFO Parity Error" }, + { F_PCIE_INIC_MA_ARB_FIFO_PERR, "PCIe-INIC Arbiter FIFO Parity Error" }, + { F_PCIE_INIC_ARB_RSPPERR, "PCIe-INIC Arbiter Response Parity Error" }, + { F_ITE_CACHE_PERR, "GIC500 ITE Cache SRAM Parity Error" }, + { 0 } + }; static const struct intr_info arm_perr_cause1 = { .name = "ARM_PERR_INT_CAUSE1", .cause_reg = A_ARM_PERR_INT_CAUSE1, .enable_reg = A_ARM_PERR_INT_ENB1, .fatal = 0xffffffff, .flags = IHF_IGNORE_IF_DISABLED | IHF_FATAL_IFF_ENABLED, - .details = NULL, + .details = arm_perr_int_cause1_details, .actions = NULL, }; + static const struct intr_details arm_perr_int_cause2_details[] = { + { F_INIC_WSTRB_FIFO_PERR, "AXI2MA_128 INIC Write Strobe FIFO Parity Error" }, + { F_INIC_BID_FIFO_PERR, "AXI2MA_128 INIC bID FIFO Parity Error" }, + { F_CC_SRAM_PKA_PERR, "CryptoCell ram_pka_wrapper FIFO Parity Error" }, + { F_CC_SRAM_SEC_PERR, "CryptoCell sec_sram_wrapper FIFO Parity Error" }, + { F_MESS2AXI4_PARERR, "Message2AXI4 IBQ I/P Interface Parity Error" }, + { F_CCI2INIC_INTF_PARERR, "CCI2INIC Response Interface Parity Error" }, + { 0 } + }; static const struct intr_info arm_perr_cause2 = { .name = "ARM_PERR_INT_CAUSE2", .cause_reg = A_ARM_PERR_INT_CAUSE2, .enable_reg = A_ARM_PERR_INT_ENB2, .fatal = 0xffffffff, .flags = IHF_IGNORE_IF_DISABLED | IHF_FATAL_IFF_ENABLED, - .details = NULL, + .details = arm_perr_int_cause2_details, .actions = NULL, }; + static const struct intr_details arm_cerr_int_cause0_details[] = { + { F_WRDATA_FIFO0_CERR, "AXI2MA M0 Write Data FIFO Correctable Error" }, + { F_WRDATA_FIFO1_CERR, "AXI2MA M1 Write Data FIFO Correctable Error" }, + { F_WR512DATAFIFO0_CERR, "AXI2MA M0 Write Data 512b FIFO Correctable Error" }, + { F_WR512DATAFIFO1_CERR, "AXI2MA M1 Write Data 512b FIFO Correctable Error" }, + { F_RDATAFIFO0_CERR, "AXI2MA M0 Read Data FIFO Correctable Error" }, + { F_RDATAFIFO1_CERR, "AXI2MA M1 Read Data FIFO Correctable Error" }, + { F_ROBUFF_CORERR0, "Reorder Buffer Correctable Error" }, + { F_ROBUFF_CORERR1, "Reorder Buffer Correctable Error" }, + { F_ROBUFF_CORERR2, "Reorder Buffer Correctable Error" }, + { F_ROBUFF_CORERR3, "Reorder Buffer Correctable Error" }, + { F_MA2AXI_RSPDATACORERR, "MA2AXI Response FIFO Correctable Error" }, + { 0x00180000, "AXI2RC SRAM Correctable Error" }, + { F_RC_WFIFO_OUTCERR, "AXI2RC Write FIFO Correctable Error" }, + { F_RC_RSPFIFO_CERR, "AXI2RC Response Correctable Error" }, + { F_MSI_MEM_CERR, "MSI Memory FIFO Correctable Error" }, + { F_INIC_WRDATA_FIFO_CERR, "INIC Write Data FIFO Correctable Error" }, + { F_INIC_RDATAFIFO_CERR, "INIC Read Data FIFO Correctable Error" }, + { 0x00003000, "ARM Doorbell SRAM Correctable Error" }, + { F_ICB_RAM_CERR, "ICB SRAM Parity Error" }, + { F_CC_SRAM_PKA_CERR, "CryptoCell ram_pka_wrapper FIFO Correctable Error" }, + { F_CC_SRAM_SEC_CERR, "CryptoCell sec_sram_wrapper FIFO Correctable Error" }, + { 0 } + }; static const struct intr_info arm_cerr_cause0 = { - .name = "ARM_CERR_INT_CAUSE", + .name = "ARM_CERR_INT_CAUSE0", .cause_reg = A_ARM_CERR_INT_CAUSE0, .enable_reg = A_ARM_CERR_INT_ENB0, .fatal = 0, .flags = IHF_IGNORE_IF_DISABLED | IHF_FATAL_IFF_ENABLED, - .details = NULL, + .details = arm_cerr_int_cause0_details, .actions = NULL, }; + static const struct intr_details arm_err_int_cause0_details[] = { + { F_STRB0_ERROR, "Strobe Error from AXI2MA 0" }, + { F_STRB1_ERROR, "Strobe Error from AXI2MA 1" }, + { F_PCIE_INIC_MA_ARB_INV_RSP_TAG, "Invalid Response Tag for PCIE-INIc MA ARB" }, + { F_ERROR0_NOCMD_DATA, "AXI2MA 0 No Command Data Error" }, + { F_ERROR1_NOCMD_DATA, "AXI2MA 1 No Command Data Error" }, + { F_INIC_STRB_ERROR, "AXI2MA_128b INIC Strobe Error" }, + { 0 } + }; static const struct intr_info arm_err_cause0 = { - .name = "ARM_ERR_INT_CAUSE", + .name = "ARM_ERR_INT_CAUSE0", .cause_reg = A_ARM_ERR_INT_CAUSE0, .enable_reg = A_ARM_ERR_INT_ENB0, .fatal = 0, .flags = IHF_IGNORE_IF_DISABLED | IHF_FATAL_IFF_ENABLED, - .details = NULL, + .details = arm_err_int_cause0_details, .actions = NULL, }; + + static const struct intr_details arm_peripheral_int_cause_details[] = { + { F_TIMER_INT, "TIMER_INT" }, + { F_NVME_INT, "NVME_INT" }, + { F_EMMC_WAKEUP_INT, "EMMC_WAKEUP_INT" }, + { F_EMMC_INT, "EMMC_INT" }, + { F_USB_MC_INT, "USB_MC_INT" }, + { F_USB_DMA_INT, "USB_DMA_INT" }, + { 0 } + }; static const struct intr_info arm_periph_cause = { .name = "ARM_PERIPHERAL_INT_CAUSE", .cause_reg = A_ARM_PERIPHERAL_INT_CAUSE, .enable_reg = A_ARM_PERIPHERAL_INT_ENB, .fatal = 0, .flags = IHF_IGNORE_IF_DISABLED | IHF_FATAL_IFF_ENABLED, - .details = NULL, + .details = arm_peripheral_int_cause_details, .actions = NULL, }; + static const struct intr_details arm_arm_uart_int_cause_details[] = { + { F_RX_FIFO_NOT_EMPTY, "intcause for uart rx fifo" }, + { F_TX_FIFO_EMPTY, "intcause for uart tx fifo" }, + { 0 } + }; + static const struct intr_info arm_uart_cause = { + .name = "ARM_ARM_UART_INT_CAUSE", + .cause_reg = A_ARM_ARM_UART_INT_CAUSE, + .enable_reg = A_ARM_ARM_UART_INT_EN, + .fatal = 0, + .flags = IHF_FATAL_IFF_ENABLED, + .details = arm_arm_uart_int_cause_details, + .actions = NULL, + }; + static const struct intr_details arm_nvme_db_emu_int_cause_details[] = { + { F_INVALID_BRESP, "Invalid CCI Write Response" }, + { F_DATA_LEN_OF, + "Incorrect Write Request to be written to incorrect Devices/Regions" }, + { F_INVALID_EMU_ADDR, "Invalid Emulation Address Range Configuration" }, + { F_INVALID_AXI_ADDR_CFG, "Invalid AXI Address Configuration" }, + { 0 } + }; static const struct intr_info arm_nvme_db_emu_cause = { .name = "ARM_NVME_DB_EMU_INT_CAUSE", .cause_reg = A_ARM_NVME_DB_EMU_INT_CAUSE, .enable_reg = A_ARM_NVME_DB_EMU_INT_ENABLE, .fatal = 0, .flags = IHF_IGNORE_IF_DISABLED | IHF_FATAL_IFF_ENABLED, - .details = NULL, + .details = arm_nvme_db_emu_int_cause_details, .actions = NULL, }; bool fatal = false; @@ -6785,12 +8245,13 @@ static bool arm_intr_handler(struct adapter *adap, int idx, int flags) fatal |= t4_handle_intr(adap, &arm_err_cause0, 0, flags); fatal |= t4_handle_intr(adap, &arm_periph_cause, 0, flags); fatal |= t4_handle_intr(adap, &arm_nvme_db_emu_cause, 0, flags); + fatal |= t4_handle_intr(adap, &arm_uart_cause, 0, flags); return (fatal); } static inline uint32_t -get_perr_ucause(struct adapter *sc, const struct intr_info *ii) +get_ucause(struct adapter *sc, const struct intr_info *ii) { uint32_t cause; @@ -6977,7 +8438,8 @@ bool t4_slow_intr_handler(struct adapter *adap, int flags) .cause_reg = A_PL_PERR_CAUSE, .enable_reg = A_PL_PERR_ENABLE, .fatal = 0xffffffff, - .flags = IHF_IGNORE_IF_DISABLED | IHF_FATAL_IFF_ENABLED, + .flags = IHF_IGNORE_IF_DISABLED | IHF_FATAL_IFF_ENABLED | + IHF_CLR_DELAYED, .details = pl_int_cause_fields, .actions = NULL, }; @@ -7117,7 +8579,8 @@ bool t4_slow_intr_handler(struct adapter *adap, int flags) .cause_reg = A_PL_PERR_CAUSE, .enable_reg = A_PL_PERR_ENABLE, .fatal = 0xffffffff, - .flags = IHF_IGNORE_IF_DISABLED | IHF_FATAL_IFF_ENABLED, + .flags = IHF_IGNORE_IF_DISABLED | IHF_FATAL_IFF_ENABLED | + IHF_CLR_DELAYED, .details = t7_pl_perr_cause_fields, .actions = NULL, }; @@ -7125,23 +8588,19 @@ bool t4_slow_intr_handler(struct adapter *adap, int flags) uint32_t perr; if (chip_id(adap) < CHELSIO_T7) { - perr = get_perr_ucause(adap, &pl_perr_cause); - fatal |= t4_handle_intr(adap, &pl_perr_cause, 0, - flags & ~(IHF_CLR_ALL_SET | IHF_CLR_ALL_UNIGNORED)); + perr = get_ucause(adap, &pl_perr_cause); + fatal |= t4_handle_intr(adap, &pl_perr_cause, 0, flags); fatal |= t4_handle_intr(adap, &pl_int_cause, t4_perr_to_ic(adap, perr), flags); - t4_write_reg(adap, pl_perr_cause.cause_reg, perr); - (void)t4_read_reg(adap, pl_perr_cause.cause_reg); + clear_int_cause_reg(adap, &pl_perr_cause, flags); } else { - perr = get_perr_ucause(adap, &t7_pl_perr_cause); - fatal |= t4_handle_intr(adap, &t7_pl_perr_cause, 0, - flags & ~(IHF_CLR_ALL_SET | IHF_CLR_ALL_UNIGNORED)); + perr = get_ucause(adap, &t7_pl_perr_cause); + fatal |= t4_handle_intr(adap, &t7_pl_perr_cause, 0, flags); fatal |= t4_handle_intr(adap, &t7_pl_int_cause, t7_perr_to_ic1(perr), flags); fatal |= t4_handle_intr(adap, &t7_pl_int_cause2, t7_perr_to_ic2(perr), flags); - t4_write_reg(adap, t7_pl_perr_cause.cause_reg, perr); - (void)t4_read_reg(adap, t7_pl_perr_cause.cause_reg); + clear_int_cause_reg(adap, &t7_pl_perr_cause, flags); } return (fatal); } diff --git a/sys/dev/ffec/if_ffec.c b/sys/dev/ffec/if_ffec.c index 17fab283fc81..cf171a854406 100644 --- a/sys/dev/ffec/if_ffec.c +++ b/sys/dev/ffec/if_ffec.c @@ -850,7 +850,7 @@ ffec_rxfinish_onebuf(struct ffec_softc *sc, int len) * biggest header is, instead of the whole 1530ish-byte frame. */ if (sc->fecflags & FECFLAG_RACC) { - m->m_data = mtod(m, uint8_t *) + 2; + m_adj(m, 2); } else { src = mtod(m, uint8_t*); dst = src - ETHER_ALIGN; diff --git a/sys/dev/sound/pcm/sound.c b/sys/dev/sound/pcm/sound.c index d98952d7a984..235142eb5209 100644 --- a/sys/dev/sound/pcm/sound.c +++ b/sys/dev/sound/pcm/sound.c @@ -77,11 +77,30 @@ snd_setup_intr(device_t dev, struct resource *res, int flags, driver_intr_t hand return bus_setup_intr(dev, res, flags, NULL, hand, param, cookiep); } +static void +pcm_hotswap(void) +{ + struct snddev_info *d; + char buf[32]; + + bus_topo_assert(); + if (snd_unit >= 0) { + d = devclass_get_softc(pcm_devclass, snd_unit); + if (!PCM_REGISTERED(d)) + return; + snprintf(buf, sizeof(buf), "cdev=dsp%d", snd_unit); + if (d->reccount > 0) + devctl_notify("SND", "CONN", "IN", buf); + if (d->playcount > 0) + devctl_notify("SND", "CONN", "OUT", buf); + } else + devctl_notify("SND", "CONN", "NODEV", NULL); +} + static int sysctl_hw_snd_default_unit(SYSCTL_HANDLER_ARGS) { struct snddev_info *d; - char buf[32]; int error, unit; unit = snd_unit; @@ -95,13 +114,8 @@ sysctl_hw_snd_default_unit(SYSCTL_HANDLER_ARGS) } snd_unit = unit; snd_unit_auto = 0; + pcm_hotswap(); bus_topo_unlock(); - - snprintf(buf, sizeof(buf), "cdev=dsp%d", snd_unit); - if (d->reccount > 0) - devctl_notify("SND", "CONN", "IN", buf); - if (d->playcount > 0) - devctl_notify("SND", "CONN", "OUT", buf); } return (error); } @@ -373,6 +387,7 @@ int pcm_register(device_t dev, char *str) { struct snddev_info *d = device_get_softc(dev); + int err; /* should only be called once */ if (d->flags & SD_F_REGISTERED) @@ -417,6 +432,13 @@ pcm_register(device_t dev, char *str) vchan_initsys(dev); feeder_eq_initsys(dev); + sndstat_register(dev, SNDST_TYPE_PCM, d->status); + + err = dsp_make_dev(dev); + if (err) + return (err); + + bus_topo_lock(); if (snd_unit_auto < 0) snd_unit_auto = (snd_unit < 0) ? 1 : 0; if (snd_unit < 0 || snd_unit_auto > 1) @@ -424,9 +446,11 @@ pcm_register(device_t dev, char *str) else if (snd_unit_auto == 1) snd_unit = pcm_best_unit(snd_unit); - sndstat_register(dev, SNDST_TYPE_PCM, d->status); + if (snd_unit == device_get_unit(dev)) + pcm_hotswap(); + bus_topo_unlock(); - return (dsp_make_dev(dev)); + return (0); } int @@ -469,13 +493,14 @@ pcm_unregister(device_t dev) cv_destroy(&d->cv); mtx_destroy(&d->lock); + bus_topo_lock(); if (snd_unit == device_get_unit(dev)) { snd_unit = pcm_best_unit(-1); if (snd_unit_auto == 0) snd_unit_auto = 1; - if (snd_unit < 0) - devctl_notify("SND", "CONN", "NODEV", NULL); + pcm_hotswap(); } + bus_topo_unlock(); return (0); } diff --git a/sys/dev/sound/usb/uaudio.c b/sys/dev/sound/usb/uaudio.c index 27d5009da4fa..eedd52774b70 100644 --- a/sys/dev/sound/usb/uaudio.c +++ b/sys/dev/sound/usb/uaudio.c @@ -5386,8 +5386,8 @@ uaudio_mixer_bsd2value(struct uaudio_mixer_node *mc, int val) } static void -uaudio_mixer_ctl_set(struct uaudio_softc *sc, struct uaudio_mixer_node *mc, - uint8_t chan, int val) +uaudio_mixer_ctl_set(struct uaudio_softc *sc, unsigned index, + struct uaudio_mixer_node *mc, uint8_t chan, int val) { val = uaudio_mixer_bsd2value(mc, val); @@ -5396,7 +5396,9 @@ uaudio_mixer_ctl_set(struct uaudio_softc *sc, struct uaudio_mixer_node *mc, /* start the transfer, if not already started */ + mtx_lock(&sc->sc_child[index].mixer_lock); usbd_transfer_start(sc->sc_mixer_xfer[0]); + mtx_unlock(&sc->sc_child[index].mixer_lock); } static void @@ -5482,7 +5484,7 @@ uaudio_mixer_set(struct uaudio_softc *sc, struct snd_mixer *m, for (mc = sc->sc_mixer_root; mc != NULL; mc = mc->next) { if (mc->ctl == type) { for (chan = 0; chan < mc->nchan; chan++) { - uaudio_mixer_ctl_set(sc, mc, chan, + uaudio_mixer_ctl_set(sc, index, mc, chan, chan == 0 ? left : right); } } @@ -5523,7 +5525,7 @@ uaudio_mixer_setrecsrc(struct uaudio_softc *sc, struct snd_mixer *m, uint32_t sr for (i = mc->minval; (i > 0) && (i <= mc->maxval); i++) { if (temp != (1U << mc->slctrtype[i - 1])) continue; - uaudio_mixer_ctl_set(sc, mc, 0, i); + uaudio_mixer_ctl_set(sc, index, mc, 0, i); break; } } diff --git a/sys/dev/uart/uart_dev_ns8250.c b/sys/dev/uart/uart_dev_ns8250.c index c13eabe9055e..d6940dc80005 100644 --- a/sys/dev/uart/uart_dev_ns8250.c +++ b/sys/dev/uart/uart_dev_ns8250.c @@ -529,40 +529,40 @@ UART_CLASS(uart_ns8250_class); */ #ifdef DEV_ACPI static struct acpi_spcr_compat_data acpi_spcr_compat_data[] = { - { &uart_ns8250_class, ACPI_DBG2_16550_COMPATIBLE }, - { &uart_ns8250_class, ACPI_DBG2_16550_SUBSET }, - { &uart_ns8250_class, ACPI_DBG2_16550_WITH_GAS }, + { &uart_ns8250_class, ACPI_DBG2_16550_COMPATIBLE }, + { &uart_ns8250_class, ACPI_DBG2_16550_SUBSET }, + { &uart_ns8250_class, ACPI_DBG2_16550_WITH_GAS }, { NULL, 0 }, }; UART_ACPI_SPCR_CLASS(acpi_spcr_compat_data); static struct acpi_uart_compat_data acpi_compat_data[] = { {"AMD0020", &uart_ns8250_class, 2, 0, 48000000, UART_F_BUSY_DETECT, "AMD / Synopsys Designware UART"}, - {"AMDI0020", &uart_ns8250_class, 2, 0, 48000000, UART_F_BUSY_DETECT, "AMD / Synopsys Designware UART"}, - {"APMC0D08", &uart_ns8250_class, 2, 4, 0, 0, "APM compatible UART"}, - {"MRVL0001", &uart_ns8250_class, 2, 0, 200000000, UART_F_BUSY_DETECT, "Marvell / Synopsys Designware UART"}, - {"SCX0006", &uart_ns8250_class, 2, 0, 62500000, UART_F_BUSY_DETECT, "SynQuacer / Synopsys Designware UART"}, - {"HISI0031", &uart_ns8250_class, 2, 0, 200000000, UART_F_BUSY_DETECT, "HiSilicon / Synopsys Designware UART"}, - {"INTC1006", &uart_ns8250_class, 2, 0, 25000000, 0, "Intel ARM64 UART"}, - {"NXP0018", &uart_ns8250_class, 0, 0, 350000000, UART_F_BUSY_DETECT, "NXP / Synopsys Designware UART"}, - {"PNP0500", &uart_ns8250_class, 0, 0, 0, 0, "Standard PC COM port"}, - {"PNP0501", &uart_ns8250_class, 0, 0, 0, 0, "16550A-compatible COM port"}, - {"PNP0502", &uart_ns8250_class, 0, 0, 0, 0, "Multiport serial device (non-intelligent 16550)"}, - {"PNP0510", &uart_ns8250_class, 0, 0, 0, 0, "Generic IRDA-compatible device"}, - {"PNP0511", &uart_ns8250_class, 0, 0, 0, 0, "Generic IRDA-compatible device"}, - {"WACF004", &uart_ns8250_class, 0, 0, 0, 0, "Wacom Tablet PC Screen"}, - {"WACF00E", &uart_ns8250_class, 0, 0, 0, 0, "Wacom Tablet PC Screen 00e"}, - {"FUJ02E5", &uart_ns8250_class, 0, 0, 0, 0, "Wacom Tablet at FuS Lifebook T"}, - {NULL, NULL, 0 , 0, 0, 0, NULL}, + {"AMDI0020", &uart_ns8250_class, 2, 0, 48000000, UART_F_BUSY_DETECT, "AMD / Synopsys Designware UART"}, + {"APMC0D08", &uart_ns8250_class, 2, 4, 0, 0, "APM compatible UART"}, + {"MRVL0001", &uart_ns8250_class, 2, 0, 200000000, UART_F_BUSY_DETECT, "Marvell / Synopsys Designware UART"}, + {"SCX0006", &uart_ns8250_class, 2, 0, 62500000, UART_F_BUSY_DETECT, "SynQuacer / Synopsys Designware UART"}, + {"HISI0031", &uart_ns8250_class, 2, 0, 200000000, UART_F_BUSY_DETECT, "HiSilicon / Synopsys Designware UART"}, + {"INTC1006", &uart_ns8250_class, 2, 0, 25000000, 0, "Intel ARM64 UART"}, + {"NXP0018", &uart_ns8250_class, 0, 0, 350000000, UART_F_BUSY_DETECT, "NXP / Synopsys Designware UART"}, + {"PNP0500", &uart_ns8250_class, 0, 0, 0, 0, "Standard PC COM port"}, + {"PNP0501", &uart_ns8250_class, 0, 0, 0, 0, "16550A-compatible COM port"}, + {"PNP0502", &uart_ns8250_class, 0, 0, 0, 0, "Multiport serial device (non-intelligent 16550)"}, + {"PNP0510", &uart_ns8250_class, 0, 0, 0, 0, "Generic IRDA-compatible device"}, + {"PNP0511", &uart_ns8250_class, 0, 0, 0, 0, "Generic IRDA-compatible device"}, + {"WACF004", &uart_ns8250_class, 0, 0, 0, 0, "Wacom Tablet PC Screen"}, + {"WACF00E", &uart_ns8250_class, 0, 0, 0, 0, "Wacom Tablet PC Screen 00e"}, + {"FUJ02E5", &uart_ns8250_class, 0, 0, 0, 0, "Wacom Tablet at FuS Lifebook T"}, + {NULL, NULL, 0, 0, 0, 0, NULL}, }; UART_ACPI_CLASS_AND_DEVICE(acpi_compat_data); #endif #ifdef FDT static struct ofw_compat_data compat_data[] = { - {"ns16550", (uintptr_t)&uart_ns8250_class}, - {"ns16550a", (uintptr_t)&uart_ns8250_class}, - {NULL, (uintptr_t)NULL}, + {"ns16550", (uintptr_t)&uart_ns8250_class}, + {"ns16550a", (uintptr_t)&uart_ns8250_class}, + {NULL, (uintptr_t)NULL}, }; UART_FDT_CLASS_AND_DEVICE(compat_data); #endif diff --git a/sys/dev/uart/uart_dev_pl011.c b/sys/dev/uart/uart_dev_pl011.c index ae3c4d3218cf..f0d7bcda1fa4 100644 --- a/sys/dev/uart/uart_dev_pl011.c +++ b/sys/dev/uart/uart_dev_pl011.c @@ -382,32 +382,32 @@ static struct uart_class uart_pl011_class = { }; UART_CLASS(uart_pl011_class); -#ifdef FDT -static struct ofw_compat_data fdt_compat_data[] = { - {"arm,pl011", (uintptr_t)&uart_pl011_class}, - {NULL, (uintptr_t)NULL}, -}; -UART_FDT_CLASS_AND_DEVICE(fdt_compat_data); -#endif - #ifdef DEV_ACPI static struct acpi_spcr_compat_data acpi_spcr_compat_data[] = { - { &uart_pl011_class, ACPI_DBG2_ARM_PL011 }, - { &uart_pl011_class, ACPI_DBG2_ARM_SBSA_GENERIC }, - { &uart_pl011_class, ACPI_DBG2_ARM_SBSA_32BIT }, + { &uart_pl011_class, ACPI_DBG2_ARM_PL011 }, + { &uart_pl011_class, ACPI_DBG2_ARM_SBSA_GENERIC }, + { &uart_pl011_class, ACPI_DBG2_ARM_SBSA_32BIT }, { NULL, 0 }, }; UART_ACPI_SPCR_CLASS(acpi_spcr_compat_data); static struct acpi_uart_compat_data acpi_compat_data[] = { - {"ARMH0011", &uart_pl011_class, 2, 0, 0, 0, "uart pl011"}, - {"ARMHB000", &uart_pl011_class, 2, 0, 0, 0, "uart pl011"}, - {"ARMHB000", &uart_pl011_class, 2, 0, 0, 0, "uart pl011"}, - {NULL, NULL, 0, 0, 0, 0, NULL}, + {"ARMH0011", &uart_pl011_class, 2, 0, 0, 0, "uart pl011"}, + {"ARMHB000", &uart_pl011_class, 2, 0, 0, 0, "uart pl011"}, + {"ARMHB000", &uart_pl011_class, 2, 0, 0, 0, "uart pl011"}, + {NULL, NULL, 0, 0, 0, 0, NULL}, }; UART_ACPI_CLASS_AND_DEVICE(acpi_compat_data); #endif +#ifdef FDT +static struct ofw_compat_data fdt_compat_data[] = { + {"arm,pl011", (uintptr_t)&uart_pl011_class}, + {NULL, (uintptr_t)NULL}, +}; +UART_FDT_CLASS_AND_DEVICE(fdt_compat_data); +#endif + static int uart_pl011_bus_attach(struct uart_softc *sc) { diff --git a/sys/dev/usb/usb_transfer.c b/sys/dev/usb/usb_transfer.c index 67745cf49397..d41121ed3a06 100644 --- a/sys/dev/usb/usb_transfer.c +++ b/sys/dev/usb/usb_transfer.c @@ -1889,8 +1889,10 @@ usbd_transfer_submit(struct usb_xfer *xfer) */ #if USB_HAVE_BUSDMA if (xfer->flags_int.bdma_enable) { + USB_BUS_LOCK(bus); /* insert the USB transfer last in the BUS-DMA queue */ usb_command_wrapper(&xfer->xroot->dma_q, xfer); + USB_BUS_UNLOCK(bus); return; } #endif diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c index af0841c75549..b889c4a14866 100644 --- a/sys/kern/imgact_elf.c +++ b/sys/kern/imgact_elf.c @@ -93,8 +93,8 @@ static int __elfN(check_header)(const Elf_Ehdr *hdr); static const Elf_Brandinfo *__elfN(get_brandinfo)(struct image_params *imgp, - const char *interp, int32_t *osrel, uint32_t *fctl0); -static int __elfN(load_file)(struct proc *p, const char *file, u_long *addr, + const Elf_Phdr *phdr, const char *interp, int32_t *osrel, uint32_t *fctl0); +static int __elfN(load_file)(struct thread *td, const char *file, u_long *addr, u_long *entry); static int __elfN(load_section)(const struct image_params *imgp, vm_ooffset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, @@ -103,7 +103,7 @@ static int __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp); static bool __elfN(freebsd_trans_osrel)(const Elf_Note *note, int32_t *osrel); static bool kfreebsd_trans_osrel(const Elf_Note *note, int32_t *osrel); -static bool __elfN(check_note)(struct image_params *imgp, +static bool __elfN(check_note)(struct image_params *imgp, const Elf_Phdr *phdr, const Elf_Brandnote *checknote, int32_t *osrel, bool *has_fctl0, uint32_t *fctl0); static vm_prot_t __elfN(trans_prot)(Elf_Word); @@ -227,6 +227,11 @@ SYSCTL_BOOL(ELF_NODE_OID, OID_AUTO, allow_wx, CTLFLAG_RWTUN, &__elfN(allow_wx), 0, "Allow pages to be mapped simultaneously writable and executable"); +static u_int __elfN(phnums) = 128; +SYSCTL_UINT(ELF_NODE_OID, OID_AUTO, phnums, + CTLFLAG_RWTUN, &__elfN(phnums), 0, + "Max number of program headers to accept"); + static const Elf_Brandinfo *elf_brand_list[MAX_BRANDS]; #define aligned(a, t) (rounddown2((u_long)(a), sizeof(t)) == (u_long)(a)) @@ -339,8 +344,8 @@ __elfN(brand_inuse)(const Elf_Brandinfo *entry) } static const Elf_Brandinfo * -__elfN(get_brandinfo)(struct image_params *imgp, const char *interp, - int32_t *osrel, uint32_t *fctl0) +__elfN(get_brandinfo)(struct image_params *imgp, const Elf_Phdr *phdr, + const char *interp, int32_t *osrel, uint32_t *fctl0) { const Elf_Ehdr *hdr = (const Elf_Ehdr *)imgp->image_header; const Elf_Brandinfo *bi, *bi_m; @@ -369,8 +374,8 @@ __elfN(get_brandinfo)(struct image_params *imgp, const char *interp, has_fctl0 = false; *fctl0 = 0; *osrel = 0; - ret = __elfN(check_note)(imgp, bi->brand_note, osrel, - &has_fctl0, fctl0); + ret = __elfN(check_note)(imgp, phdr, bi->brand_note, + osrel, &has_fctl0, fctl0); /* Give brand a chance to veto check_note's guess */ if (ret && bi->header_supported) { ret = bi->header_supported(imgp, osrel, @@ -780,19 +785,20 @@ __elfN(load_sections)(const struct image_params *imgp, const Elf_Ehdr *hdr, * the entry point for the loaded file. */ static int -__elfN(load_file)(struct proc *p, const char *file, u_long *addr, - u_long *entry) +__elfN(load_file)(struct thread *td, const char *file, u_long *addr, + u_long *entry) { struct { struct nameidata nd; struct vattr attr; struct image_params image_params; - } *tempdata; + } *tempdata = NULL; const Elf_Ehdr *hdr = NULL; const Elf_Phdr *phdr = NULL; struct nameidata *nd; struct vattr *attr; struct image_params *imgp; + void *m_phdrs = NULL; u_long rbase; u_long base_addr = 0; int error; @@ -802,7 +808,7 @@ __elfN(load_file)(struct proc *p, const char *file, u_long *addr, * XXXJA: This check can go away once we are sufficiently confident * that the checks in namei() are correct. */ - if (IN_CAPABILITY_MODE(curthread)) + if (IN_CAPABILITY_MODE(td)) return (ECAPMODE); #endif @@ -814,7 +820,8 @@ __elfN(load_file)(struct proc *p, const char *file, u_long *addr, /* * Initialize part of the common data */ - imgp->proc = p; + imgp->td = td; + imgp->proc = td->td_proc; imgp->attr = attr; NDINIT(nd, LOOKUP, ISOPEN | FOLLOW | LOCKSHARED | LOCKLEAF, @@ -851,24 +858,32 @@ __elfN(load_file)(struct proc *p, const char *file, u_long *addr, goto fail; } - /* Only support headers that fit within first page for now */ - if (!__elfN(phdr_in_zero_page)(hdr)) { + if (!aligned(imgp->image_header + hdr->e_phoff, Elf_Addr) || + hdr->e_phnum > __elfN(phnums)) { error = ENOEXEC; goto fail; } - - phdr = (const Elf_Phdr *)(imgp->image_header + hdr->e_phoff); - if (!aligned(phdr, Elf_Addr)) { - error = ENOEXEC; - goto fail; + if (__elfN(phdr_in_zero_page)(hdr)) { + phdr = (const Elf_Phdr *)(imgp->image_header + hdr->e_phoff); + } else { + VOP_UNLOCK(imgp->vp); + phdr = m_phdrs = malloc(hdr->e_phnum * sizeof(Elf_Phdr), + M_TEMP, M_WAITOK | M_ZERO); + vn_lock(imgp->vp, LK_SHARED | LK_RETRY); + error = vn_rdwr(UIO_READ, imgp->vp, m_phdrs, + hdr->e_phnum * sizeof(Elf_Phdr), hdr->e_phoff, + UIO_SYSSPACE, IO_NODELOCKED, imgp->td->td_ucred, + NOCRED, NULL, imgp->td); + if (error != 0) + goto fail; } error = __elfN(load_sections)(imgp, hdr, phdr, rbase, &base_addr); if (error != 0) goto fail; - if (p->p_sysent->sv_protect != NULL) - p->p_sysent->sv_protect(imgp, SVP_INTERP); + if (imgp->proc->p_sysent->sv_protect != NULL) + imgp->proc->p_sysent->sv_protect(imgp, SVP_INTERP); *addr = base_addr; *entry = (unsigned long)hdr->e_entry + rbase; @@ -882,6 +897,7 @@ fail: VOP_UNSET_TEXT_CHECKED(nd->ni_vp); vput(nd->ni_vp); } + free(m_phdrs, M_TEMP); free(tempdata, M_TEMP); return (error); @@ -1008,7 +1024,6 @@ static int __elfN(get_interp)(struct image_params *imgp, const Elf_Phdr *phdr, char **interpp, bool *free_interpp) { - struct thread *td; char *interp; int error, interp_name_len; @@ -1016,8 +1031,6 @@ __elfN(get_interp)(struct image_params *imgp, const Elf_Phdr *phdr, ("%s: p_type %u != PT_INTERP", __func__, phdr->p_type)); ASSERT_VOP_LOCKED(imgp->vp, __func__); - td = curthread; - /* Path to interpreter */ if (phdr->p_filesz < 2 || phdr->p_filesz > MAXPATHLEN) { uprintf("Invalid PT_INTERP\n"); @@ -1045,8 +1058,8 @@ __elfN(get_interp)(struct image_params *imgp, const Elf_Phdr *phdr, error = vn_rdwr(UIO_READ, imgp->vp, interp, interp_name_len, phdr->p_offset, - UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, - NOCRED, NULL, td); + UIO_SYSSPACE, IO_NODELOCKED, imgp->td->td_ucred, + NOCRED, NULL, imgp->td); if (error != 0) { free(interp, M_TEMP); uprintf("i/o error PT_INTERP %d\n", error); @@ -1079,13 +1092,13 @@ __elfN(load_interp)(struct image_params *imgp, const Elf_Brandinfo *brand_info, if (brand_info->interp_newpath != NULL && (brand_info->interp_path == NULL || strcmp(interp, brand_info->interp_path) == 0)) { - error = __elfN(load_file)(imgp->proc, + error = __elfN(load_file)(imgp->td, brand_info->interp_newpath, addr, entry); if (error == 0) return (0); } - error = __elfN(load_file)(imgp->proc, interp, addr, entry); + error = __elfN(load_file)(imgp->td, interp, addr, entry); if (error == 0) return (0); @@ -1102,7 +1115,6 @@ __elfN(load_interp)(struct image_params *imgp, const Elf_Brandinfo *brand_info, static int __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) { - struct thread *td; const Elf_Ehdr *hdr; const Elf_Phdr *phdr; Elf_Auxargs *elf_auxargs; @@ -1111,6 +1123,7 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) char *interp; const Elf_Brandinfo *brand_info; struct sysentvec *sv; + void *m_phdrs; u_long addr, baddr, entry, proghdr; u_long maxalign, maxsalign, mapsz, maxv, maxv1, anon_loc; uint32_t fctl0; @@ -1135,16 +1148,6 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) * detected an ELF file. */ - if (!__elfN(phdr_in_zero_page)(hdr)) { - uprintf("Program headers not in the first page\n"); - return (ENOEXEC); - } - phdr = (const Elf_Phdr *)(imgp->image_header + hdr->e_phoff); - if (!aligned(phdr, Elf_Addr)) { - uprintf("Unaligned program headers\n"); - return (ENOEXEC); - } - n = error = 0; baddr = 0; osrel = 0; @@ -1152,7 +1155,35 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) entry = proghdr = 0; interp = NULL; free_interp = false; - td = curthread; + m_phdrs = NULL; + + if (!aligned(imgp->image_header + hdr->e_phoff, Elf_Addr)) { + uprintf("Unaligned program headers\n"); + return (ENOEXEC); + } + if (hdr->e_phoff + hdr->e_phnum * hdr->e_phentsize < hdr->e_phoff) { + uprintf("PHDRS wrap\n"); + return (ENOEXEC); + } + if (hdr->e_phnum > __elfN(phnums)) { + uprintf("Too many program headers (%u, %u max)\n", + hdr->e_phnum, __elfN(phnums)); + return (ENOEXEC); + } + if (__elfN(phdr_in_zero_page)(hdr)) { + phdr = (const Elf_Phdr *)(imgp->image_header + hdr->e_phoff); + } else { + VOP_UNLOCK(imgp->vp); + phdr = m_phdrs = malloc(hdr->e_phnum * sizeof(Elf_Phdr), + M_TEMP, M_WAITOK | M_ZERO); + vn_lock(imgp->vp, LK_SHARED | LK_RETRY); + error = vn_rdwr(UIO_READ, imgp->vp, m_phdrs, + hdr->e_phnum * sizeof(Elf_Phdr), hdr->e_phoff, + UIO_SYSSPACE, IO_NODELOCKED, imgp->td->td_ucred, + NOCRED, NULL, imgp->td); + if (error != 0) + goto ret; + } /* * Somewhat arbitrary, limit accepted max alignment for the @@ -1234,7 +1265,7 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) } } - brand_info = __elfN(get_brandinfo)(imgp, interp, &osrel, &fctl0); + brand_info = __elfN(get_brandinfo)(imgp, phdr, interp, &osrel, &fctl0); if (brand_info == NULL) { uprintf("ELF binary type \"%u\" not known.\n", hdr->e_ident[EI_OSABI]); @@ -1329,7 +1360,7 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) map = &vmspace->vm_map; maxv = sv->sv_usrstack; if ((imgp->map_flags & MAP_ASLR_STACK) == 0) - maxv -= lim_max(td, RLIMIT_STACK); + maxv -= lim_max(imgp->td, RLIMIT_STACK); if (error == 0 && mapsz >= maxv - vm_map_min(map)) { uprintf("Excessive mapping size\n"); error = ENOEXEC; @@ -1339,7 +1370,7 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) KASSERT((map->flags & MAP_ASLR) != 0, ("ET_DYN_ADDR_RAND but !MAP_ASLR")); error = __CONCAT(rnd_, __elfN(base))(map, - vm_map_min(map) + mapsz + lim_max(td, RLIMIT_DATA), + vm_map_min(map) + mapsz + lim_max(imgp->td, RLIMIT_DATA), /* reserve half of the address space to interpreter */ maxv / 2, maxalign, &imgp->et_dyn_addr); } @@ -1362,7 +1393,7 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) * calculation is that it leaves room for the heap to grow to * its maximum allowed size. */ - addr = round_page((vm_offset_t)vmspace->vm_daddr + lim_max(td, + addr = round_page((vm_offset_t)vmspace->vm_daddr + lim_max(imgp->td, RLIMIT_DATA)); if ((map->flags & MAP_ASLR) != 0) { maxv1 = maxv / 2 + addr / 2; @@ -1438,6 +1469,7 @@ ret: ASSERT_VOP_LOCKED(imgp->vp, "skipped relock"); if (free_interp) free(interp, M_TEMP); + free(m_phdrs, M_TEMP); return (error); } @@ -2809,7 +2841,7 @@ __elfN(parse_notes)(const struct image_params *imgp, const Elf_Note *checknote, } error = vn_rdwr(UIO_READ, imgp->vp, buf, pnote->p_filesz, pnote->p_offset, UIO_SYSSPACE, IO_NODELOCKED, - curthread->td_ucred, NOCRED, NULL, curthread); + imgp->td->td_ucred, NOCRED, NULL, imgp->td); if (error != 0) { uprintf("i/o error PT_NOTE\n"); goto retf; @@ -2918,17 +2950,16 @@ note_fctl_cb(const Elf_Note *note, void *arg0, bool *res) * as for headers. */ static bool -__elfN(check_note)(struct image_params *imgp, const Elf_Brandnote *brandnote, - int32_t *osrel, bool *has_fctl0, uint32_t *fctl0) +__elfN(check_note)(struct image_params *imgp, const Elf_Phdr *phdr, + const Elf_Brandnote *brandnote, int32_t *osrel, bool *has_fctl0, + uint32_t *fctl0) { - const Elf_Phdr *phdr; const Elf_Ehdr *hdr; struct brandnote_cb_arg b_arg; struct fctl_cb_arg f_arg; int i, j; hdr = (const Elf_Ehdr *)imgp->image_header; - phdr = (const Elf_Phdr *)(imgp->image_header + hdr->e_phoff); b_arg.brandnote = brandnote; b_arg.osrel = osrel; f_arg.has_fctl0 = has_fctl0; diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 958ec559fd8d..4066682cbcc5 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -448,6 +448,7 @@ do_execve(struct thread *td, struct image_args *args, struct mac *mac_p, */ bzero(imgp, sizeof(*imgp)); imgp->proc = p; + imgp->td = td; imgp->attr = &attr; imgp->args = args; oldcred = p->p_ucred; diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index b3e1d4be9fee..1032f6cd1bf0 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -1430,7 +1430,7 @@ _Out_ _Contains_timet_ struct ffclock_estimate *cest ); } -244 AUE_NULL STD { +244 AUE_NULL STD|CAPENABLED { int clock_nanosleep( clockid_t clock_id, int flags, diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index 66d2c610139f..84b175b42eec 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -2805,7 +2805,6 @@ in_pcbrehash(struct inpcb *inp) struct inpcbinfo *pcbinfo = inp->inp_pcbinfo; struct inpcbhead *head; uint32_t hash; - bool connected; INP_WLOCK_ASSERT(inp); INP_HASH_WLOCK_ASSERT(pcbinfo); @@ -2815,34 +2814,24 @@ in_pcbrehash(struct inpcb *inp) #ifdef INET6 if (inp->inp_vflag & INP_IPV6) { + MPASS(!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)); hash = INP6_PCBHASH(&inp->in6p_faddr, inp->inp_lport, inp->inp_fport, pcbinfo->ipi_hashmask); - connected = !IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr); } else #endif { + MPASS(!in_nullhost(inp->inp_faddr)); hash = INP_PCBHASH(&inp->inp_faddr, inp->inp_lport, inp->inp_fport, pcbinfo->ipi_hashmask); - connected = !in_nullhost(inp->inp_faddr); } /* See the comment in in_pcbinshash(). */ - if (connected && (inp->inp_flags & INP_INLBGROUP) != 0) + if ((inp->inp_flags & INP_INLBGROUP) != 0) in_pcbremlbgrouphash(inp); - /* - * When rehashing, the caller must ensure that either the new or the old - * foreign address was unspecified. - */ - if (connected) { - CK_LIST_REMOVE(inp, inp_hash_wild); - head = &pcbinfo->ipi_hash_exact[hash]; - CK_LIST_INSERT_HEAD(head, inp, inp_hash_exact); - } else { - CK_LIST_REMOVE(inp, inp_hash_exact); - head = &pcbinfo->ipi_hash_wild[hash]; - CK_LIST_INSERT_HEAD(head, inp, inp_hash_wild); - } + CK_LIST_REMOVE(inp, inp_hash_wild); + head = &pcbinfo->ipi_hash_exact[hash]; + CK_LIST_INSERT_HEAD(head, inp, inp_hash_exact); } void diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c index 8132899bb0d9..0cf6be2f9b33 100644 --- a/sys/netinet6/in6_pcb.c +++ b/sys/netinet6/in6_pcb.c @@ -465,15 +465,6 @@ in6_pcbconnect(struct inpcb *inp, struct sockaddr_in6 *sin6, struct ucred *cred, bzero(&laddr6, sizeof(laddr6)); laddr6.sin6_family = AF_INET6; - if (V_fib_hash_outbound) { - uint32_t hash_type, hash_val; - - hash_val = fib6_calc_software_hash(&inp->in6p_laddr, - &sin6->sin6_addr, 0, sin6->sin6_port, - inp->inp_socket->so_proto->pr_protocol, &hash_type); - inp->inp_flowid = hash_val; - inp->inp_flowtype = hash_type; - } /* * Call inner routine, to assign local interface address. * in6_pcbladdr() may automatically fill in sin6_scope_id. @@ -520,6 +511,16 @@ in6_pcbconnect(struct inpcb *inp, struct sockaddr_in6 *sin6, struct ucred *cred, in_pcbrehash(inp); INP_HASH_WUNLOCK(pcbinfo); + if (V_fib_hash_outbound) { + uint32_t hash_type, hash_val; + + hash_val = fib6_calc_software_hash(&inp->in6p_laddr, + &sin6->sin6_addr, 0, sin6->sin6_port, + inp->inp_socket->so_proto->pr_protocol, &hash_type); + inp->inp_flowid = hash_val; + inp->inp_flowtype = hash_type; + } + return (0); } diff --git a/sys/netlink/route/iface_drivers.c b/sys/netlink/route/iface_drivers.c index 31d2523a479b..79daa4215dba 100644 --- a/sys/netlink/route/iface_drivers.c +++ b/sys/netlink/route/iface_drivers.c @@ -69,21 +69,24 @@ _nl_modify_ifp_generic(struct ifnet *ifp, struct nl_parsed_link *lattrs, int error; if (lattrs->ifla_ifalias != NULL) { - if (nlp_has_priv(npt->nlp, PRIV_NET_SETIFDESCR)) { - int len = strlen(lattrs->ifla_ifalias) + 1; - char *buf = if_allocdescr(len, M_WAITOK); - - memcpy(buf, lattrs->ifla_ifalias, len); - if_setdescr(ifp, buf); - if_setlastchange(ifp); - } else { + if (!nlp_has_priv(npt->nlp, PRIV_NET_SETIFDESCR)) { nlmsg_report_err_msg(npt, "Not enough privileges to set descr"); return (EPERM); } + int len = strlen(lattrs->ifla_ifalias) + 1; + char *buf = if_allocdescr(len, M_WAITOK); + + memcpy(buf, lattrs->ifla_ifalias, len); + if_setdescr(ifp, buf); + if_setlastchange(ifp); } if ((lattrs->ifi_change & IFF_UP) != 0 || lattrs->ifi_change == 0) { /* Request to up or down the interface */ + if (!nlp_has_priv(npt->nlp, PRIV_NET_SETIFFLAGS)) { + nlmsg_report_err_msg(npt, "Not enough privileges to set flags"); + return (EPERM); + } if (lattrs->ifi_flags & IFF_UP) if_up(ifp); else @@ -91,22 +94,21 @@ _nl_modify_ifp_generic(struct ifnet *ifp, struct nl_parsed_link *lattrs, } if (lattrs->ifla_mtu > 0) { - if (nlp_has_priv(npt->nlp, PRIV_NET_SETIFMTU)) { - struct ifreq ifr = { .ifr_mtu = lattrs->ifla_mtu }; - error = ifhwioctl(SIOCSIFMTU, ifp, (char *)&ifr, - curthread); - if (error != 0) { - nlmsg_report_err_msg(npt, "Failed to set mtu"); - return (error); - } - } else { + if (!nlp_has_priv(npt->nlp, PRIV_NET_SETIFMTU)) { nlmsg_report_err_msg(npt, "Not enough privileges to set mtu"); return (EPERM); } + struct ifreq ifr = { .ifr_mtu = lattrs->ifla_mtu }; + error = ifhwioctl(SIOCSIFMTU, ifp, (char *)&ifr, + curthread); + if (error != 0) { + nlmsg_report_err_msg(npt, "Failed to set mtu"); + return (error); + } } if ((lattrs->ifi_change & IFF_PROMISC) != 0 || - lattrs->ifi_change == 0) + lattrs->ifi_change == 0) { /* * When asking for IFF_PROMISC, set permanent flag instead * (IFF_PPROMISC) as we have no way of doing promiscuity @@ -114,24 +116,28 @@ _nl_modify_ifp_generic(struct ifnet *ifp, struct nl_parsed_link *lattrs, * function either sets or unsets IFF_PROMISC, and ifi_change * is usually set to 0xFFFFFFFF. */ + if (!nlp_has_priv(npt->nlp, PRIV_NET_SETIFFLAGS)) { + nlmsg_report_err_msg(npt, "Not enough privileges to set promisc"); + return (EPERM); + } if_setppromisc(ifp, (lattrs->ifi_flags & IFF_PROMISC) != 0); + } if (lattrs->ifla_address != NULL) { - if (nlp_has_priv(npt->nlp, PRIV_NET_SETIFMAC)) { - error = if_setlladdr(ifp, - NLA_DATA(lattrs->ifla_address), - NLA_DATA_LEN(lattrs->ifla_address)); - if (error != 0) { - nlmsg_report_err_msg(npt, - "setting IFLA_ADDRESS failed with error code: %d", - error); - return (error); - } - } else { + if (!nlp_has_priv(npt->nlp, PRIV_NET_SETIFMAC)) { nlmsg_report_err_msg(npt, "Not enough privileges to set IFLA_ADDRESS"); return (EPERM); } + error = if_setlladdr(ifp, + NLA_DATA(lattrs->ifla_address), + NLA_DATA_LEN(lattrs->ifla_address)); + if (error != 0) { + nlmsg_report_err_msg(npt, + "setting IFLA_ADDRESS failed with error code: %d", + error); + return (error); + } } return (0); diff --git a/sys/netlink/route/rt.c b/sys/netlink/route/rt.c index ee17737426ed..39ecb537d365 100644 --- a/sys/netlink/route/rt.c +++ b/sys/netlink/route/rt.c @@ -217,7 +217,7 @@ dump_rc_nhg(struct nl_writer *nw, const struct route_nhop_data *rnd, struct rtms return; rtnh->rtnh_flags = 0; rtnh->rtnh_ifindex = if_getindex(wn[i].nh->nh_ifp); - rtnh->rtnh_hops = wn[i].weight; + rtnh->rtnh_hops = MIN(wn[i].weight, UINT8_MAX); dump_rc_nhop_gw(nw, wn[i].nh); uint32_t rtflags = nhop_get_rtflags(wn[i].nh); if (rtflags != base_rtflags) @@ -242,7 +242,8 @@ dump_rc_nhg(struct nl_writer *nw, const struct route_nhop_data *rnd, struct rtms } nlattr_set_len(nw, off); nlattr_add_u32(nw, NL_RTA_PRIORITY, nhop_metric); - nlattr_add_u32(nw, NL_RTA_WEIGHT, nhop_weight); + if (nhop_weight != RT_DEFAULT_WEIGHT) + nlattr_add_u32(nw, NL_RTA_WEIGHT, nhop_weight); } static void @@ -977,6 +978,14 @@ create_nexthop_from_attrs(struct nl_parsed_route *attrs, return (nh); } +/* pre-2.6.19 Linux API compatibility: prefer RTA_TABLE, fall back to rtm_table */ +static inline void +old_linux_compat(struct nl_parsed_route *attrs) +{ + if (attrs->rtm_table > 0 && attrs->rta_table == 0) + attrs->rta_table = attrs->rtm_table; +} + static int rtnl_handle_newroute(struct nlmsghdr *hdr, struct nlpcb *nlp, struct nl_pstate *npt) @@ -996,9 +1005,7 @@ rtnl_handle_newroute(struct nlmsghdr *hdr, struct nlpcb *nlp, return (EINVAL); } - /* pre-2.6.19 Linux API compatibility */ - if (attrs.rtm_table > 0 && attrs.rta_table == 0) - attrs.rta_table = attrs.rtm_table; + old_linux_compat(&attrs); if (attrs.rta_table >= V_rt_numfibs || attrs.rtm_family > AF_MAX) { NLMSG_REPORT_ERR_MSG(npt, "invalid fib"); return (EINVAL); @@ -1065,6 +1072,7 @@ rtnl_handle_delroute(struct nlmsghdr *hdr, struct nlpcb *nlp, return (ESRCH); } + old_linux_compat(&attrs); if (attrs.rta_table >= V_rt_numfibs || attrs.rtm_family > AF_MAX) { NLMSG_REPORT_ERR_MSG(npt, "invalid fib"); return (EINVAL); @@ -1088,6 +1096,7 @@ rtnl_handle_getroute(struct nlmsghdr *hdr, struct nlpcb *nlp, struct nl_pstate * if (error != 0) return (error); + old_linux_compat(&attrs); if (attrs.rta_table >= V_rt_numfibs || attrs.rtm_family > AF_MAX) { NLMSG_REPORT_ERR_MSG(npt, "invalid fib"); return (EINVAL); diff --git a/sys/security/mac_do/mac_do.c b/sys/security/mac_do/mac_do.c index ba49da22ce67..93f2084d1c93 100644 --- a/sys/security/mac_do/mac_do.c +++ b/sys/security/mac_do/mac_do.c @@ -1,8 +1,9 @@ -/*- +/* * SPDX-License-Identifier: BSD-2-Clause * - * Copyright(c) 2024 Baptiste Daroussin <bapt@FreeBSD.org> - * Copyright (c) 2024 The FreeBSD Foundation + * Copyright (c) 2024 Baptiste Daroussin <bapt@FreeBSD.org> + * Copyright (c) 2024, 2026, The FreeBSD Foundation + * Copyright (c) 2025 Kushagra Srivastava <kushagra1403@gmail.com> * * Portions of this software were developed by Olivier Certner * <olce.freebsd@certner.fr> at Kumacom SARL under sponsorship from the FreeBSD @@ -23,6 +24,7 @@ #include <sys/priv.h> #include <sys/proc.h> #include <sys/refcount.h> +#include <sys/rmlock.h> #include <sys/socket.h> #include <sys/stdarg.h> #include <sys/sx.h> @@ -32,6 +34,24 @@ #include <security/mac/mac_policy.h> + +#ifdef INVARIANTS +/* + * Should typically be moved to libkern (and perhaps libc) at some point, and be + * optimized if to be used outside of INVARIANTS. + */ +static bool +is_zeroed(const void *const buf, const size_t size) +{ + const char *const p = buf; + + for (size_t i = 0; i < size; ++i) + if (p[i] != 0) + return (false); + return (true); +} +#endif + static SYSCTL_NODE(_security_mac, OID_AUTO, do, CTLFLAG_RW|CTLFLAG_MPSAFE, 0, "mac_do policy controls"); @@ -46,7 +66,16 @@ SYSCTL_INT(_security_mac_do, OID_AUTO, print_parse_error, CTLFLAG_RWTUN, static MALLOC_DEFINE(M_MAC_DO, "mac_do", "mac_do(4) security module"); -#define MAC_RULE_STRING_LEN 1024 +#define MAX_RULE_STRING_SIZE 1024 +_Static_assert(MAX_RULE_STRING_SIZE > 0, + "MAX_RULE_STRING_SIZE: No space for the NUL terminator!"); + +#define MAX_EXEC_PATHS_SIZE 2048 +#define MAX_EXEC_PATHS 8 +_Static_assert(MAX_EXEC_PATHS_SIZE > 0, + "MAX_EXEC_PATHS_SIZE: No space for the NUL terminator!"); + +struct rmlock mac_do_rml; static unsigned osd_jail_slot; static unsigned osd_thread_slot; @@ -67,6 +96,11 @@ static const char *id_type_to_str[] = { #define PARSE_ERROR_SIZE 256 +/* + * All functions having a parse error parameter must return through it a parse + * error object if and only if they return an error value (non-zero); else, NULL + * must be returned through it. + */ struct parse_error { size_t pos; char msg[PARSE_ERROR_SIZE]; @@ -123,11 +157,15 @@ typedef uint16_t flags_t; #define MDF_MAY_REJ_SUPP (1u << 11) /* (t,gid) Some explicit ID (not MDF_CURRENT) has MDF_SUPP_MUST. */ #define MDF_EXPLICIT_SUPP_MUST (1u << 12) -/* (t,gid) Whether any target clause is about primary groups. Used during - * parsing only. */ +/* + * (t,gid) Whether any target clause is about primary groups. Used during + * parsing only. + */ #define MDF_HAS_PRIMARY_CLAUSE (1u << 13) -/* (t,gid) Whether any target clause is about supplementary groups. Used during - * parsing only. */ +/* + * (t,gid) Whether any target clause is about supplementary groups. Used during + * parsing only. + */ #define MDF_HAS_SUPP_CLAUSE (1u << 14) #define MDF_TYPE_GID_MASK (MDF_ANY_SUPP | MDF_MAY_REJ_SUPP | \ MDF_EXPLICIT_SUPP_MUST | MDF_HAS_PRIMARY_CLAUSE | MDF_HAS_SUPP_CLAUSE) @@ -144,7 +182,7 @@ struct id_spec { /* * This limits the number of target clauses per type to 65535. With the current - * value of MAC_RULE_STRING_LEN (1024), this is way more than enough anyway. + * value of MAX_RULE_STRING_SIZE (1024), this is way more than enough anyway. */ typedef uint16_t id_nb_t; /* We only have a few IT_* types. */ @@ -165,8 +203,24 @@ struct rule { STAILQ_HEAD(rulehead, rule); struct rules { - char string[MAC_RULE_STRING_LEN]; + char string[MAX_RULE_STRING_SIZE]; struct rulehead head; +}; + +struct exec_paths { + char exec_paths_str[MAX_EXEC_PATHS_SIZE]; + char exec_paths[MAX_EXEC_PATHS][PATH_MAX]; + int exec_path_count; +}; + +/* + * Once in use, i.e., being pointed to by a jail, a configuration structure MUST + * NEVER CHANGE (except for the 'use_count' field). This invariant is + * fundamental to correctness! + */ +struct conf { + struct rules rules; + struct exec_paths exec_paths; volatile u_int use_count __aligned(CACHE_LINE_SIZE); }; @@ -181,6 +235,7 @@ struct id_elem { STAILQ_HEAD(id_list, id_elem); + #ifdef INVARIANTS static void check_type(const id_type_t type) @@ -221,7 +276,7 @@ check_type_and_id_flags(const id_type_t type, const flags_t flags) } break; default: - __assert_unreachable(); + __assert_unreachable(); } return; @@ -281,6 +336,18 @@ unexpected_flags: #define check_type_and_type_flags(...) #endif /* INVARIANTS */ +static bool +has_rules(const struct rules *const rules) +{ + return (rules->string[0] != '\0'); +} + +static bool +has_exec_paths(const struct exec_paths *const exec_paths) +{ + return (exec_paths->exec_paths_str[0] != '\0'); +} + /* * Returns EALREADY if both flags have some overlap, or EINVAL if flags are * incompatible, else 0 with flags successfully merged into 'dest'. @@ -323,23 +390,36 @@ toast_rules(struct rules *const rules) free(rule->gids, M_MAC_DO); free(rule, M_MAC_DO); } - free(rules, M_MAC_DO); } -static struct rules * -alloc_rules(void) +static inline void +init_rules(struct rules *const rules) { - struct rules *const rules = malloc(sizeof(*rules), M_MAC_DO, M_WAITOK); - - _Static_assert(MAC_RULE_STRING_LEN > 0, "MAC_RULE_STRING_LEN <= 0!"); - rules->string[0] = 0; + MPASS(is_zeroed(rules, sizeof(*rules))); STAILQ_INIT(&rules->head); - rules->use_count = 0; - return (rules); +} + +static inline void +init_exec_paths(struct exec_paths *const exec_paths) +{ + MPASS(is_zeroed(exec_paths, sizeof(*exec_paths))); +} + +static struct conf * +new_conf(void) +{ + struct conf *const conf = malloc(sizeof(*conf), M_MAC_DO, + M_WAITOK | M_ZERO); + + init_rules(&conf->rules); + init_exec_paths(&conf->exec_paths); + refcount_init(&conf->use_count, 1); + + return (conf); } static bool -is_null_or_empty(const char *s) +is_null_or_empty(const char *const s) { return (s == NULL || s[0] == '\0'); } @@ -433,7 +513,8 @@ static void make_parse_error(struct parse_error **const parse_error, const size_t pos, const char *const fmt, ...) { - struct parse_error *const err = malloc(sizeof(*err), M_MAC_DO, M_WAITOK); + struct parse_error *const err = malloc(sizeof(*err), M_MAC_DO, + M_WAITOK); va_list ap; err->pos = pos; @@ -740,6 +821,7 @@ parse_target_clause(char *to, struct rule *const rule, check_type_and_finish: check_type_and_type_flags(type, *tflags); finish: + MPASS(error == 0 && *parse_error == NULL); return (0); einval: /* We must have built a parse error on error. */ @@ -817,7 +899,7 @@ pour_list_into_rule(const id_type_t type, struct id_list *const list, make_parse_error(parse_error, 0, "Incompatible flags or duplicate " "GID %u.", id); - return (EINVAL); + goto einval; } check_type_and_id_flags(type, array[ref_idx].flags); @@ -831,7 +913,7 @@ pour_list_into_rule(const id_type_t type, struct id_list *const list, */ make_parse_error(parse_error, 0, "Duplicate UID %u.", id); - return (EINVAL); + goto einval; default: __assert_unreachable(); @@ -840,7 +922,12 @@ pour_list_into_rule(const id_type_t type, struct id_list *const list, *nb = ref_idx + 1; } + MPASS(*parse_error == NULL); return (0); + +einval: + MPASS(*parse_error != NULL); + return (EINVAL); } /* @@ -966,6 +1053,7 @@ parse_single_rule(char *rule, struct rules *const rules, } STAILQ_INSERT_TAIL(&rules->head, new, r_entries); + MPASS(error == 0 && *parse_error == NULL); return (0); einval: @@ -983,13 +1071,13 @@ einval: /* * Parse rules specification and produce rule structures out of it. * - * Returns 0 on success, with '*rulesp' made to point to a 'struct rule' - * representing the rules. On error, the returned value is non-zero and - * '*rulesp' is unchanged. If 'string' has length greater or equal to - * MAC_RULE_STRING_LEN, ENAMETOOLONG is returned. If it is not in the expected - * format, EINVAL is returned. If an error is returned, '*parse_error' is set - * to point to a 'struct parse_error' giving an error message for the problem, - * else '*parse_error' is set to NULL. + * Must be called with '*parse_error' set to NULL. Returns 0 on success, with + * '*rulesp' made to point to a 'struct rule' representing the rules. On error, + * the returned value is non-zero and '*rulesp' is unchanged. If 'string' has + * length greater or equal to MAX_RULE_STRING_SIZE, ENAMETOOLONG is returned. If + * it is not in the expected format, EINVAL is returned. If an error is + * returned, '*parse_error' is set to point to a 'struct parse_error' giving an + * error message for the problem. * * Expected format: A >-colon-separated list of rules of the form * "<from>><target>" (for backwards compatibility, a semi-colon ":" is accepted @@ -1007,24 +1095,20 @@ einval: * - "gid=1010>gid=1011,gid=1012,gid=1013" */ static int -parse_rules(const char *const string, struct rules **const rulesp, +parse_rules(const char *const string, struct rules *const rules, struct parse_error **const parse_error) { const size_t len = strlen(string); char *copy, *p, *rule; - struct rules *rules; int error = 0; - *parse_error = NULL; - - if (len >= MAC_RULE_STRING_LEN) { + if (len >= MAX_RULE_STRING_SIZE) { make_parse_error(parse_error, 0, "Rule specification string is too long (%zu, max %zu)", - len, MAC_RULE_STRING_LEN - 1); + len, MAX_RULE_STRING_SIZE - 1); return (ENAMETOOLONG); } - rules = alloc_rules(); bcopy(string, rules->string, len + 1); MPASS(rules->string[len] == '\0'); /* Catch some races. */ @@ -1040,72 +1124,188 @@ parse_rules(const char *const string, struct rules **const rulesp, if (error != 0) { (*parse_error)->pos += rule - copy; toast_rules(rules); - goto out; + goto error; + } + } + + MPASS(error == 0 && *parse_error == NULL); +out: + free(copy, M_MAC_DO); + return (error); +error: + MPASS(error != 0 && *parse_error != NULL); + goto out; +} + +/* + * Similar constraints as parse_rules() (which see). + */ +static int +parse_exec_paths(const char *const string, struct exec_paths *const exec_paths, + struct parse_error **const parse_error) +{ + const size_t len = strlen(string); + char *copy, *p, *path; + int error = 0; + + if (len >= MAX_EXEC_PATHS_SIZE) { + make_parse_error(parse_error, 0, + "Exec path specification string is too long (%zu, max %u)", + len, MAX_EXEC_PATHS_SIZE - 1); + return (ENAMETOOLONG); + } + + bcopy(string, exec_paths->exec_paths_str, len + 1); + MPASS(exec_paths->exec_paths_str[len] == '\0'); + + copy = malloc(len + 1, M_MAC_DO, M_WAITOK); + bcopy(string, copy, len + 1); + MPASS(copy[len] == '\0'); + + p = copy; + while ((path = strsep(&p, ":")) != NULL) { + size_t path_len; + + if (*path == '\0') + continue; + + if (exec_paths->exec_path_count >= MAX_EXEC_PATHS) { + make_parse_error(parse_error, path - copy, + "Too many exec paths specified (max %d)", + MAX_EXEC_PATHS); + error = EINVAL; + goto error; } + + path_len = strlen(path); + if (path_len >= PATH_MAX) { + make_parse_error(parse_error, path - copy, + "Exec paths too long (%zu, max %u)", + path_len, PATH_MAX - 1); + error = ENAMETOOLONG; + goto error; + } + + strlcpy(exec_paths->exec_paths[exec_paths->exec_path_count], + path, PATH_MAX); + exec_paths->exec_path_count++; } - *rulesp = rules; + MPASS(error == 0 && *parse_error == NULL); out: free(copy, M_MAC_DO); return (error); +error: + MPASS(error != 0 && *parse_error != NULL); + goto out; +} + +static void +hold_conf(struct conf *const conf) +{ + int old_count __diagused = refcount_acquire(&conf->use_count); + + KASSERT(old_count != 0, + ("MAC/do: Trying to resurrect a destroyed configuration.")); +} + +static void +drop_conf(struct conf *const conf) +{ + if (refcount_release(&conf->use_count)) { + toast_rules(&conf->rules); + free(conf, M_MAC_DO); + } } /* - * Find rules applicable to the passed prison. + * Find configuration applicable to the passed prison. + * + * Returns the applicable configuration (which always exists), with an + * additional reference that must be freed by the caller. 'pr' must not be + * locked. + * + * The applicable configuration is that of the closest ancestor prison + * (including itself) of the passed prison that actually has a 'struct conf' + * associated to it. * - * Returns the applicable rules (and never NULL). 'pr' must be unlocked. - * 'aprp' is set to the (ancestor) prison holding these, and it must be unlocked - * once the caller is done accessing the rules. '*aprp' is equal to 'pr' if and - * only if the current jail has its own set of rules. + * If 'hpr' is not NULL, it is used to return a pointer to the (unlocked) prison + * holding the applicable configuration. + * + * The find_conf_unlocked() variant needs 'mac_do_rml' to be (read- or write-) + * locked. The find_conf() variant will take a read lock for the duration of + * the search. + * + * The configuration returned by this function is sequentially consistent with + * other concurrent reads and configuration modifications, even in the presence + * of concurrent changes of configurations higher up in the jail tree (whether + * they "change" the value of some parameters, install a new configuration where + * there wasn't any, breaking inheritance from higher up, or remove an existing + * one, establishing inheritance from higher up). */ -static struct rules * -find_rules(struct prison *const pr, struct prison **const aprp) +static struct conf * +find_conf_locked(struct prison *const pr, struct prison **const hpr) { - struct prison *cpr, *ppr; - struct rules *rules; + struct prison *cpr, *ppr; /* Current and parent. */ + struct conf *conf; + rm_assert(&mac_do_rml, RA_LOCKED); + /* + * We do not need to take any locks here to climb the prison tree as + * either the start prison ('pr') is that of the current thread (and our + * ancestors are necessarily stable), or it is a prison passed by the jail + * machinery to an OSD method, in which case the prison tree lock is + * already being held. + */ cpr = pr; for (;;) { - prison_lock(cpr); - rules = osd_jail_get(cpr, osd_jail_slot); - if (rules != NULL) + conf = osd_jail_get_unlocked(cpr, osd_jail_slot); + if (conf != NULL) break; - prison_unlock(cpr); ppr = cpr->pr_parent; - MPASS(ppr != NULL); /* prison0 always has rules. */ + /* + * 'prison0' always has a mac_do(4) configuration because we + * installed one on module load/activation and nothing can + * destroy it as 'prison0' is not a regular jail and the + * 'mac.do' parameter cannot be set to 'inherit' on it, which is + * the only way to clear an existing configuration. + */ + KASSERT(ppr != NULL, + ("MAC/do: 'prison0' must always have a configuration.")); cpr = ppr; } - *aprp = cpr; - return (rules); + hold_conf(conf); + if (hpr != NULL) + *hpr = cpr; + return (conf); } -static void -hold_rules(struct rules *const rules) +static struct conf * +find_conf(struct prison *const pr, struct prison **const hpr) { - refcount_acquire(&rules->use_count); -} + struct conf *conf; + struct rm_priotracker rmpt; -static void -drop_rules(struct rules *const rules) -{ - if (refcount_release(&rules->use_count)) - toast_rules(rules); + rm_rlock(&mac_do_rml, &rmpt); + conf = find_conf_locked(pr, hpr); + rm_runlock(&mac_do_rml, &rmpt); + return (conf); } #ifdef INVARIANTS static void -check_rules_use_count(const struct rules *const rules, u_int expected) +check_conf_use_count(const struct conf *const conf, u_int expected) { - const u_int use_count = refcount_load(&rules->use_count); + const u_int use_count = refcount_load(&conf->use_count); if (use_count != expected) - panic("MAC/do: Rules at %p: Use count is %u, expected %u", - rules, use_count, expected); + panic("MAC/do: Configuration at %p: Use count is %u, " + "expected %u", conf, use_count, expected); } #else -#define check_rules_use_count(...) +#define check_conf_use_count(...) #endif /* INVARIANTS */ /* @@ -1117,7 +1317,7 @@ check_rules_use_count(const struct rules *const rules, u_int expected) static void dealloc_jail_osd(void *const value) { - struct rules *const rules = value; + struct conf *const conf = value; /* * If called because the "holding" jail goes down, no one should be @@ -1133,124 +1333,259 @@ dealloc_jail_osd(void *const value) * we ensure that all thread's slots are freed first in mac_do_destroy() * to be able to check that only one reference remains. */ - check_rules_use_count(rules, 1); - toast_rules(rules); + check_conf_use_count(conf, 1); + drop_conf(conf); +} + +/* + * Sets a mac_do(4) configuration on a jail. + * + * 'conf' is the new conf to set (can be NULL), and an additional reference will + * be taken on it to represent the jail holding it (if not NULL). 'rsv' must + * have been allocated through osd_reserve() (if 'conf' is not NULL; else can + * be NULL). + * + * The previous configuration on the jail (or NULL) is returned (with an + * associated reference if not NULL). + */ +static struct conf * +set_conf_locked(struct prison *const pr, struct conf *const conf, + void **const rsv) +{ + struct conf *old_conf; + int error __diagused; + + KASSERT(conf == NULL || rsv != NULL, + ("MAC/do: OSD reserve needed to avoid allocating memory")); + rm_assert(&mac_do_rml, RA_WLOCKED); + + if (conf != NULL) + hold_conf(conf); + old_conf = osd_jail_get_unlocked(pr, osd_jail_slot); + error = osd_jail_set_reserved(pr, osd_jail_slot, rsv, conf); + KASSERT(error == 0, ("MAC/do: osd_jail_set_reserved() failed " + "with 'conf' = %p and 'rsv' = %p", conf, rsv)); + if (conf == NULL) + /* + * This completely frees the OSD slot, but doesn't call the + * destructor since we've just put NULL into the slot. + */ + osd_jail_del(pr, osd_jail_slot); + return (old_conf); +} + +/* + * Immediately replace the jail's configuration. + * + * To be used only if the configuration to set does not depend in any way on the + * currently applicable configuration. + * + * Takes care of write-locking 'mac_do_rml', which should be unlocked on entry + * and will be unlocked on exit. + */ +static void +set_conf(struct prison *const pr, struct conf *const conf) +{ + void **const rsv = conf != NULL ? osd_reserve(osd_jail_slot) : NULL; + struct conf *old_conf; + + rm_wlock(&mac_do_rml); + old_conf = set_conf_locked(pr, conf, rsv); + rm_wunlock(&mac_do_rml); + if (old_conf != NULL) + drop_conf(old_conf); } /* * Remove the rules specifically associated to a prison. * * In practice, this means that the rules become inherited (from the closest - * ascendant that has some). + * ancestor that has some). * * Destroys the 'osd_jail_slot' slot of the passed jail. */ -static void -remove_rules(struct prison *const pr) +static struct conf * +remove_conf_locked(struct prison *const pr) { - struct rules *old_rules; - int error __unused; + return (set_conf_locked(pr, NULL, NULL)); +} - prison_lock(pr); - /* - * We burden ourselves with extracting rules first instead of just - * letting osd_jail_del() call dealloc_jail_osd() as we want to - * decrement their use count, and possibly free them, outside of the - * prison lock. - */ - old_rules = osd_jail_get(pr, osd_jail_slot); - error = osd_jail_set(pr, osd_jail_slot, NULL); - /* osd_set() never allocates memory when 'value' is NULL, nor fails. */ - MPASS(error == 0); - /* - * This completely frees the OSD slot, but doesn't call the destructor - * since we've just put NULL in the slot. - */ - osd_jail_del(pr, osd_jail_slot); - prison_unlock(pr); +static struct conf * +new_default_conf(void) +{ + const char *const mdo_path = "/usr/bin/mdo"; + struct conf *conf = new_conf(); + + strlcpy(conf->exec_paths.exec_paths_str, mdo_path, + MAX_EXEC_PATHS_SIZE); + strlcpy(conf->exec_paths.exec_paths[0], mdo_path, + PATH_MAX); + conf->exec_paths.exec_path_count = 1; - if (old_rules != NULL) - drop_rules(old_rules); + return (conf); } -/* - * Assign already built rules to a jail. - */ static void -set_rules(struct prison *const pr, struct rules *const rules) +clone_rules(struct rules *const dst, const struct rules *const src) { - struct rules *old_rules; - void **rsv; + const struct rule *src_rule; + + strlcpy(dst->string, src->string, sizeof(dst->string)); - check_rules_use_count(rules, 0); - hold_rules(rules); - rsv = osd_reserve(osd_jail_slot); + STAILQ_FOREACH(src_rule, &src->head, r_entries) { + struct rule *const dst_rule = malloc(sizeof(*dst_rule), + M_MAC_DO, M_WAITOK); + bcopy(src_rule, dst_rule, sizeof(*dst_rule)); - prison_lock(pr); - old_rules = osd_jail_get(pr, osd_jail_slot); - osd_jail_set_reserved(pr, osd_jail_slot, rsv, rules); - prison_unlock(pr); - if (old_rules != NULL) - drop_rules(old_rules); + if (src_rule->uids_nb > 0) { + const size_t uids_size = sizeof(*dst_rule->uids) * + src_rule->uids_nb; + + dst_rule->uids = malloc(uids_size, M_MAC_DO, M_WAITOK); + bcopy(src_rule->uids, dst_rule->uids, uids_size); + } + + if (src_rule->gids_nb > 0) { + const size_t gids_size = sizeof(*dst_rule->gids) * + src_rule->gids_nb; + + dst_rule->gids = malloc(gids_size, M_MAC_DO, M_WAITOK); + bcopy(src_rule->gids, dst_rule->gids, gids_size); + } + + STAILQ_INSERT_TAIL(&dst->head, dst_rule, r_entries); + } +} + +static void +clone_exec_paths(struct exec_paths *const dst, + const struct exec_paths *const src) +{ + MPASS(is_zeroed(dst, sizeof(*dst))); + dst->exec_path_count = src->exec_path_count; + for (int i = 0; i < src->exec_path_count; i++) + strlcpy(dst->exec_paths[i], src->exec_paths[i], + sizeof(dst->exec_paths[i])); + + strlcpy(dst->exec_paths_str, src->exec_paths_str, + sizeof(dst->exec_paths_str)); } /* - * Assigns empty rules to a jail. + * Sets/modifies the MAC/do configuration for a jail. + * + * Must be called with '*parse_error' set to NULL. + * + * Supports explicitly setting all parameters or only some of them. An + * unspecified parameter must be passed as NULL. The values of unspecified + * parameters are copied from those of the passed model configuration (which is + * expected to be the currently applicable configuration, i.e., that of the + * closest ancestor jail that has one). + * + * 'mac_do_rml' needs to be write-locked (and stays so). 'old_conf' serves to + * return, on no error, the old configuration with a reference (which must be + * eventually freed). */ -static void -set_empty_rules(struct prison *const pr) +static int +parse_and_set_conf(struct prison *const pr, const char *const rules_string, + const char *const exec_paths_string, const struct conf *const model_conf, + struct conf **const old_conf, struct parse_error **const parse_error) { - struct rules *const rules = alloc_rules(); + struct conf *const conf = new_conf(); + int error = 0; + + KASSERT(model_conf != NULL || + (rules_string != NULL && exec_paths_string != NULL), + ("MAC/do: %s: Model configuration needed!", __func__)); + + if (rules_string != NULL) { + error = parse_rules(rules_string, &conf->rules, parse_error); + if (error != 0) + goto error; + } + else + clone_rules(&conf->rules, &model_conf->rules); + + if (exec_paths_string != NULL) { + error = parse_exec_paths(exec_paths_string, &conf->exec_paths, + parse_error); + if (error != 0) + goto error; + } else + clone_exec_paths(&conf->exec_paths, + &model_conf->exec_paths); - set_rules(pr, rules); + MPASS(error == 0); + *old_conf = set_conf_locked(pr, conf, osd_reserve(osd_jail_slot)); + + MPASS(error == 0 && *parse_error == NULL); +out: + drop_conf(conf); + return (error); +error: + MPASS(error != 0 && *parse_error != NULL); + goto out; } /* - * Parse a rules specification and assign them to a jail. + * Calls parse_and_set_conf() and closes the current configuration transaction. * - * Returns the same error code as parse_rules() (which see). + * Closes the transaction by unlocking 'mac_do_rml' and releasing the old + * configuration returned by parse_and_set_conf(). */ static int -parse_and_set_rules(struct prison *const pr, const char *rules_string, +parse_and_commit_conf(struct prison *const pr, const char *const rules_string, + const char *const exec_paths_string, const struct conf *const model_conf, struct parse_error **const parse_error) { - struct rules *rules; + struct conf *old_conf; int error; - error = parse_rules(rules_string, &rules, parse_error); - if (error != 0) - return (error); - set_rules(pr, rules); - return (0); + error = parse_and_set_conf(pr, rules_string, exec_paths_string, + model_conf, &old_conf, parse_error); + rm_wunlock(&mac_do_rml); + + if (error == 0 && old_conf != NULL) + drop_conf(old_conf); + return (error); } + static int mac_do_sysctl_rules(SYSCTL_HANDLER_ARGS) { - char *const buf = malloc(MAC_RULE_STRING_LEN, M_MAC_DO, M_WAITOK); - struct prison *const td_pr = req->td->td_ucred->cr_prison; - struct prison *pr; - struct rules *rules; - struct parse_error *parse_error; + char *const buf = malloc(MAX_RULE_STRING_SIZE, M_MAC_DO, M_WAITOK); + struct prison *const pr = req->td->td_ucred->cr_prison; + struct conf *conf; + struct parse_error *parse_error = NULL; int error; - rules = find_rules(td_pr, &pr); - strlcpy(buf, rules->string, MAC_RULE_STRING_LEN); - prison_unlock(pr); + if (req->newptr != NULL) { + rm_wlock(&mac_do_rml); + conf = find_conf_locked(pr, NULL); + } else + conf = find_conf(pr, NULL); + strlcpy(buf, conf->rules.string, MAX_RULE_STRING_SIZE); - error = sysctl_handle_string(oidp, buf, MAC_RULE_STRING_LEN, req); - if (error != 0 || req->newptr == NULL) + error = sysctl_handle_string(oidp, buf, MAX_RULE_STRING_SIZE, req); + if (req->newptr == NULL) goto out; + if (error != 0) { + rm_wunlock(&mac_do_rml); + goto out; + } - /* Set our prison's rules, not that of the jail we inherited from. */ - error = parse_and_set_rules(td_pr, buf, &parse_error); + /* Unlocks 'mac_do_rml'. */ + error = parse_and_commit_conf(pr, buf, NULL, conf, &parse_error); if (error != 0) { if (print_parse_error) printf("MAC/do: Parse error at index %zu: %s\n", parse_error->pos, parse_error->msg); free_parse_error(parse_error); } + out: + drop_conf(conf); free(buf, M_MAC_DO); return (error); } @@ -1262,32 +1597,71 @@ SYSCTL_PROC(_security_mac_do, OID_AUTO, rules, SYSCTL_JAIL_PARAM_SYS_SUBNODE(mac, do, CTLFLAG_RW, "Jail MAC/do parameters"); -SYSCTL_JAIL_PARAM_STRING(_mac_do, rules, CTLFLAG_RW, MAC_RULE_STRING_LEN, +SYSCTL_JAIL_PARAM_STRING(_mac_do, rules, CTLFLAG_RW, MAX_RULE_STRING_SIZE, "Jail MAC/do rules"); - static int -mac_do_jail_create(void *obj, void *data __unused) +mac_do_sysctl_exec_paths(SYSCTL_HANDLER_ARGS) { - struct prison *const pr = obj; + char *const buf = malloc(MAX_EXEC_PATHS_SIZE, M_MAC_DO, M_WAITOK); + struct prison *const pr = req->td->td_ucred->cr_prison; + struct conf *conf; + struct parse_error *parse_error = NULL; + int error; - set_empty_rules(pr); - return (0); + if (req->newptr != NULL) { + rm_wlock(&mac_do_rml); + conf = find_conf_locked(pr, NULL); + } else + conf = find_conf(pr, NULL); + strlcpy(buf, conf->exec_paths.exec_paths_str, MAX_EXEC_PATHS_SIZE); + + error = sysctl_handle_string(oidp, buf, MAX_EXEC_PATHS_SIZE, req); + if (req->newptr == NULL) + goto out; + if (error != 0) { + rm_wunlock(&mac_do_rml); + goto out; + } + + /* Unlocks 'mac_do_rml'. */ + error = parse_and_commit_conf(pr, NULL, buf, conf, &parse_error); + if (error != 0) { + if (print_parse_error) + printf("MAC/do: Parse error at index %zu: %s\n", + parse_error->pos, parse_error->msg); + free_parse_error(parse_error); + } + +out: + drop_conf(conf); + free(buf, M_MAC_DO); + return (error); } +SYSCTL_PROC(_security_mac_do, OID_AUTO, exec_paths, + CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE, + 0, 0, mac_do_sysctl_exec_paths, "A", + "Colon-separated list of allowed executables"); + +SYSCTL_JAIL_PARAM_STRING(_mac_do, exec_paths, CTLFLAG_RW, MAX_EXEC_PATHS_SIZE, + "Jail MAC/do executable paths"); + static int mac_do_jail_get(void *obj, void *data) { - struct prison *ppr, *const pr = obj; + struct prison *const pr = obj; struct vfsoptlist *const opts = data; - struct rules *rules; + struct prison *hpr_out; + struct conf *const applicable_conf = find_conf(pr, &hpr_out); + const struct prison *const hpr = hpr_out; + const struct rules *const rules = &applicable_conf->rules; + const struct exec_paths *const exec_paths = &applicable_conf->exec_paths; int jsys, error; - rules = find_rules(pr, &ppr); + jsys = hpr == pr ? (has_rules(rules) && has_exec_paths(exec_paths) ? + JAIL_SYS_NEW : JAIL_SYS_DISABLE) : JAIL_SYS_INHERIT; - jsys = pr == ppr ? - (STAILQ_EMPTY(&rules->head) ? JAIL_SYS_DISABLE : JAIL_SYS_NEW) : - JAIL_SYS_INHERIT; error = vfs_setopt(opts, "mac.do", &jsys, sizeof(jsys)); if (error != 0 && error != ENOENT) goto done; @@ -1296,9 +1670,14 @@ mac_do_jail_get(void *obj, void *data) if (error != 0 && error != ENOENT) goto done; + error = vfs_setopts(opts, "mac.do.exec_paths", + exec_paths->exec_paths_str); + if (error != 0 && error != ENOENT) + goto done; + error = 0; done: - prison_unlock(ppr); + drop_conf(applicable_conf); return (error); } @@ -1317,11 +1696,16 @@ static int mac_do_jail_check(void *obj, void *data) { struct vfsoptlist *opts = data; - char *rules_string; - int error, jsys, size; + char *rules_string, *exec_paths_string; + int error, jsys, rules_size = 0, exec_paths_size = 0; + bool absent_or_empty_rules, absent_or_empty_exec_paths; error = vfs_copyopt(opts, "mac.do", &jsys, sizeof(jsys)); if (error == ENOENT) + /* + * Mark unspecified. Will fill it up below depending on the + * other options. + */ jsys = -1; else { if (error != 0) @@ -1332,75 +1716,117 @@ mac_do_jail_check(void *obj, void *data) } /* - * We use vfs_getopt() here instead of vfs_getopts() to get the length. - * We perform the additional checks done by the latter here, even if - * jail_set() calls vfs_getopts() itself later (they becoming - * inconsistent wouldn't cause any security problem). + * We use vfs_getopt() below instead of vfs_getopts() to get the + * string's buffer size. We perform the additional checks done by the + * latter here, even if jail_set() calls vfs_getopts() itself later + * (they becoming inconsistent wouldn't cause any security problem). */ - error = vfs_getopt(opts, "mac.do.rules", (void**)&rules_string, &size); - if (error == ENOENT) { - /* - * Default (in absence of "mac.do.rules") is to disable (and, in - * particular, not inherit). - */ - if (jsys == -1) - jsys = JAIL_SYS_DISABLE; - if (jsys == JAIL_SYS_NEW) { - vfs_opterror(opts, "'mac.do.rules' must be specified " - "given 'mac.do''s value"); + /* Rules. */ + error = vfs_getopt(opts, "mac.do.rules", (void **)&rules_string, + &rules_size); + if (error == ENOENT) + rules_string = NULL; + else { + if (error != 0) + return (error); + if (rules_size == 0 || rules_string[rules_size - 1] != '\0') { + vfs_opterror(opts, + "'mac.do.rules' not a proper string"); return (EINVAL); } + if (rules_size > MAX_RULE_STRING_SIZE) { + vfs_opterror(opts, "'mac.do.rules' too long"); + return (ENAMETOOLONG); + } + } - /* Absence of "mac.do.rules" at this point is OK. */ - error = 0; - } else { + /* Executable paths. */ + error = vfs_getopt(opts, "mac.do.exec_paths", + (void **)&exec_paths_string, &exec_paths_size); + if (error == ENOENT) + exec_paths_string = NULL; + else { if (error != 0) return (error); - - /* Not a proper string. */ - if (size == 0 || rules_string[size - 1] != '\0') { - vfs_opterror(opts, "'mac.do.rules' not a proper string"); + if (exec_paths_size == 0 || + exec_paths_string[exec_paths_size - 1] != '\0') { + vfs_opterror(opts, + "'mac.do.exec_paths' not a proper string"); return (EINVAL); } - - if (size > MAC_RULE_STRING_LEN) { - vfs_opterror(opts, "'mdo.rules' too long"); + if (exec_paths_size > MAX_EXEC_PATHS_SIZE) { + vfs_opterror(opts, "'mac.do.exec_paths' too long"); return (ENAMETOOLONG); } + } - if (jsys == -1) - /* Default (if "mac.do.rules" is present). */ - jsys = rules_string[0] == '\0' ? JAIL_SYS_DISABLE : - JAIL_SYS_NEW; + absent_or_empty_rules = is_null_or_empty(rules_string); + absent_or_empty_exec_paths = is_null_or_empty(exec_paths_string); + /* If not specified, infer 'jsys' from passed options. */ + if (jsys == -1) { /* - * Be liberal and accept JAIL_SYS_DISABLE and JAIL_SYS_INHERIT - * with an explicit empty rules specification. + * Default in absence of "mac.do.rules" and "mac.do.exec_paths" + * is to disable. We never implicitly inherit, as that changes + * reasoning about configurations. */ - switch (jsys) { - case JAIL_SYS_DISABLE: - case JAIL_SYS_INHERIT: - if (rules_string[0] != '\0') { - vfs_opterror(opts, "'mac.do.rules' specified " - "but should not given 'mac.do''s value"); - return (EINVAL); - } - break; + if (!absent_or_empty_rules || !absent_or_empty_exec_paths) + jsys = JAIL_SYS_NEW; + else + jsys = JAIL_SYS_DISABLE; + } + + /* Final checks based on resolved 'jsys'. */ + switch (jsys) { + case JAIL_SYS_DISABLE: + /* + * Tolerate specified but empty rules or execution paths + * (instead of not being specified). Also, tolerate that one of + * them is not empty (but not both). Indeed, as soon as one is + * empty, mac_do(4) is effectively disabled. This allows the + * administrator to still specify a value for one of them, which + * is then used for new sub-jails that do not inherit and for + * which no value for the parameter is explicitly specified + * (because then the value passed here is copied). + */ + if (!absent_or_empty_rules && !absent_or_empty_exec_paths) { + vfs_opterror(opts, + "One of 'mac.do.rules' and 'mac_do.exec_paths' " + "should not be specified or should be empty when " + "'mac.do' is 'disabled'"); + return (EINVAL); } + break; + + case JAIL_SYS_INHERIT: + /* + * Canonically, no parameters should be specified in this case. + * However, we tolerate empty ones, and also non-empty ones + * provided they match the inherited values, so that we can + * report the *resolved* value of current parameters via + * mac_do_jail_get() and have them re-applicable to this jail in + * a similar situation. Testing that inherited values are the + * same as passed ones is more expensive than a single test and + * requires some atomicity, which is why we do not perform that + * here but only in mac_do_jail_set(). + */ + break; } - return (error); + return (0); } static int mac_do_jail_set(void *obj, void *data) { - struct prison *pr = obj; - struct vfsoptlist *opts = data; - char *rules_string; - struct parse_error *parse_error; + struct prison *const pr = obj; + struct vfsoptlist *const opts = data; + char *rules_string, *exec_paths_string; + struct parse_error *parse_error = NULL; + struct conf *model_conf; int error, jsys; + bool absent_or_empty_rules, absent_or_empty_exec_paths; /* * The invariants checks used below correspond to what has already been @@ -1414,60 +1840,147 @@ mac_do_jail_set(void *obj, void *data) rules_string = vfs_getopts(opts, "mac.do.rules", &error); MPASS(error == 0 || error == ENOENT); - if (error == 0) { - MPASS(strlen(rules_string) < MAC_RULE_STRING_LEN); - if (jsys == -1) - /* Default (if "mac.do.rules" is present). */ - jsys = rules_string[0] == '\0' ? JAIL_SYS_DISABLE : - JAIL_SYS_NEW; + exec_paths_string = vfs_getopts(opts, "mac.do.exec_paths", &error); + MPASS(error == 0 || error == ENOENT); + + absent_or_empty_rules = is_null_or_empty(rules_string); + absent_or_empty_exec_paths = is_null_or_empty(exec_paths_string); + + if (jsys == -1) { + if (!absent_or_empty_rules || !absent_or_empty_exec_paths) + jsys = JAIL_SYS_NEW; else - MPASS(jsys == JAIL_SYS_NEW || - ((jsys == JAIL_SYS_DISABLE || - jsys == JAIL_SYS_INHERIT) && - rules_string[0] == '\0')); - } else { - MPASS(jsys != JAIL_SYS_NEW); - if (jsys == -1) + jsys = JAIL_SYS_DISABLE; + } + + if (jsys == JAIL_SYS_INHERIT) { + struct conf *old_conf = NULL; + + error = 0; + rm_wlock(&mac_do_rml); + + if (!absent_or_empty_rules || !absent_or_empty_exec_paths) { /* - * Default (in absence of "mac.do.rules") is to disable - * (and, in particular, not inherit). + * Some values specified. Check that they match the + * ones we are going to inherit. */ - jsys = JAIL_SYS_DISABLE; - /* If disabled, we'll store an empty rule specification. */ - if (jsys == JAIL_SYS_DISABLE) - rules_string = ""; + model_conf = find_conf_locked(pr->pr_parent, NULL); + if (strcmp(model_conf->rules.string, rules_string) + != 0) { + error = EINVAL; + vfs_opterror(opts, + "'mac.do' is 'inherited' but 'mac.do.rules'" + " was specified with a different value " + "than the one to be inherited (\"%s\")", + model_conf->rules.string); + } + if (strcmp(model_conf->exec_paths.exec_paths_str, + exec_paths_string) != 0) { + error = EINVAL; + vfs_opterror(opts, + "'mac.do' is 'inherited' but " + "'mac.do.exec_paths' was specified with a " + "different value than the one to be " + "inherited (\"%s\")", + model_conf->exec_paths.exec_paths_str); + } + drop_conf(model_conf); + } + + if (error == 0) + old_conf = remove_conf_locked(pr); + + rm_wunlock(&mac_do_rml); + + if (old_conf != NULL) + drop_conf(old_conf); + + return (error); } + model_conf = NULL; + /* Freeze configuration accesses. */ + rm_wlock(&mac_do_rml); + switch (jsys) { - case JAIL_SYS_INHERIT: - remove_rules(pr); - error = 0; - break; case JAIL_SYS_DISABLE: - case JAIL_SYS_NEW: - error = parse_and_set_rules(pr, rules_string, &parse_error); - if (error != 0) { - vfs_opterror(opts, - "MAC/do: Parse error at index %zu: %s\n", - parse_error->pos, parse_error->msg); - free_parse_error(parse_error); + /* + * mac_do(4) is disabled iff one of the parameter's string is + * empty. The parse_and_commit_conf() call below treats passing + * NULL for a parameter as a flag to copy its value from the + * relevant ancestor jail's configuration, so we have to watch + * for the final result having an empty parameter if no + * parameter has been explicitly passed as empty. Thanks to + * mac_do_jail_check(), we know that at least one parameter is + * absent or empty (see the comment for the corresponding case + * there). + */ + MPASS(absent_or_empty_rules || absent_or_empty_exec_paths); + if (!absent_or_empty_rules) + exec_paths_string = ""; + else if (!absent_or_empty_exec_paths) + rules_string = ""; + else { + /* + * Both are either empty or absent. If at least one is + * absent, we retrieve the applicable configuration as + * it will serve as a template (provides default + * values). + */ + if (rules_string == NULL || exec_paths_string == NULL) + model_conf = find_conf_locked(pr, NULL); + /* If both are absent, we have to examine if, in the + * currently applicable configuration, one of the + * parameters, which we are going to copy, is + * effectively empty. If both of those are non-empty, + * we keep the executable paths and empty the rules, + * since we expect that this is more convenient to + * administrators that may want to enable mac_do(4) + * later by just setting new rules. + */ + if (rules_string == NULL && exec_paths_string == NULL && + has_rules(&model_conf->rules) && + has_exec_paths(&model_conf->exec_paths)) + rules_string = ""; } break; + + case JAIL_SYS_NEW: + /* See the comment before the same test above. */ + if (rules_string == NULL || exec_paths_string == NULL) + model_conf = find_conf_locked(pr, NULL); + break; + default: __assert_unreachable(); } + + /* Unlocks 'mac_do_rml'. */ + error = parse_and_commit_conf(pr, rules_string, exec_paths_string, + model_conf, &parse_error); + if (model_conf != NULL) + drop_conf(model_conf); + if (error != 0) { + vfs_opterror(opts, + "MAC/do: Parse error at index %zu: %s\n", + parse_error->pos, parse_error->msg); + free_parse_error(parse_error); + } + return (error); } /* * OSD jail methods. * - * There is no PR_METHOD_REMOVE, as OSD storage is destroyed by the common jail - * code (see prison_cleanup()), which triggers a run of our dealloc_jail_osd() - * destructor. + * There is no PR_METHOD_REMOVE method, as OSD storage is destroyed by the + * common jail code (see prison_cleanup()), which triggers a run of our + * dealloc_jail_osd() destructor. There is neither a PR_METHOD_CREATE as + * PR_METHOD_SET is called just after (or the created jail destroyed if some + * PR_METHOD_CREATE fails), and our mac_do_jail_set() will ensure a jail is + * properly configured. */ static const osd_method_t osd_methods[PR_MAXMETHOD] = { - [PR_METHOD_CREATE] = mac_do_jail_create, [PR_METHOD_GET] = mac_do_jail_get, [PR_METHOD_CHECK] = mac_do_jail_check, [PR_METHOD_SET] = mac_do_jail_set, @@ -1492,8 +2005,8 @@ struct mac_do_data_header { * indicates this header is uninitialized. */ int priv; - /* Rules to apply. */ - struct rules *rules; + /* The configuration that applies. */ + struct conf *conf; }; /* @@ -1536,7 +2049,7 @@ clear_data(void *const data) struct mac_do_data_header *const hdr = data; if (hdr != NULL) { - drop_rules(hdr->rules); + drop_conf(hdr->conf); /* We don't deallocate so as to save time on next access. */ hdr->priv = 0; } @@ -1558,7 +2071,7 @@ is_data_reusable(const void *const data, const size_t size) static void set_data_header(void *const data, const size_t size, const int priv, - struct rules *const rules) + struct conf *const conf) { struct mac_do_data_header *const hdr = data; @@ -1567,7 +2080,7 @@ set_data_header(void *const data, const size_t size, const int priv, MPASS(size <= hdr->allocated_size); hdr->size = size; hdr->priv = priv; - hdr->rules = rules; + hdr->conf = conf; } /* The proc lock (and any other non-sleepable lock) must not be held. */ @@ -1933,7 +2446,7 @@ static int mac_do_priv_grant(struct ucred *cred, int priv) { struct mac_do_setcred_data *const data = fetch_data(); - const struct rules *rules; + struct rules *rules; const struct ucred *new_cred; const struct rule *rule; u_int setcred_flags; @@ -1950,7 +2463,7 @@ mac_do_priv_grant(struct ucred *cred, int priv) /* No. */ return (EPERM); - rules = data->hdr.rules; + rules = &data->hdr.conf->rules; new_cred = data->new_cred; KASSERT(new_cred != NULL, ("priv_check*() called before mac_cred_check_setcred()")); @@ -1987,7 +2500,10 @@ mac_do_priv_grant(struct ucred *cred, int priv) static int check_proc(void) { + struct prison *const pr = curproc->p_ucred->cr_prison; char *path, *to_free; + struct conf *conf; + struct exec_paths *exec_paths; int error; /* @@ -2010,7 +2526,18 @@ check_proc(void) */ if (vn_fullpath_jail(curproc->p_textvp, &path, &to_free) != 0) return (EPERM); - error = strcmp(path, "/usr/bin/mdo") == 0 ? 0 : EPERM; + + error = EPERM; + conf = find_conf(pr, NULL); + exec_paths = &conf->exec_paths; + + for (int i = 0; i < exec_paths->exec_path_count; i++) + if (strcmp(exec_paths->exec_paths[i], path) == 0) { + error = 0; + break; + } + + drop_conf(conf); free(to_free, M_TEMP); return (error); } @@ -2018,9 +2545,9 @@ check_proc(void) static void mac_do_setcred_enter(void) { - struct rules *rules; - struct prison *pr; + struct prison *const pr = curproc->p_ucred->cr_prison; struct mac_do_setcred_data * data; + struct conf *conf; int error; /* @@ -2042,9 +2569,7 @@ mac_do_setcred_enter(void) /* * Find the currently applicable rules. */ - rules = find_rules(curproc->p_ucred->cr_prison, &pr); - hold_rules(rules); - prison_unlock(pr); + conf = find_conf(pr, NULL); /* * Setup thread data to be used by other hooks. @@ -2052,7 +2577,7 @@ mac_do_setcred_enter(void) data = fetch_data(); if (!is_data_reusable(data, sizeof(*data))) data = alloc_data(data, sizeof(*data)); - set_data_header(data, sizeof(*data), PRIV_CRED_SETCRED, rules); + set_data_header(data, sizeof(*data), PRIV_CRED_SETCRED, conf); /* Not really necessary, but helps to catch programming errors. */ data->new_cred = NULL; data->setcred_flags = 0; @@ -2099,14 +2624,18 @@ mac_do_setcred_exit(void) static void mac_do_init(struct mac_policy_conf *mpc) { + struct conf *const default_conf = new_default_conf(); struct prison *pr; + rm_init_flags(&mac_do_rml, "mac_do(4)", RM_SLEEPABLE); + osd_jail_slot = osd_jail_register(dealloc_jail_osd, osd_methods); - set_empty_rules(&prison0); + set_conf(&prison0, default_conf); sx_slock(&allprison_lock); TAILQ_FOREACH(pr, &allprison, pr_list) - set_empty_rules(pr); + set_conf(pr, default_conf); sx_sunlock(&allprison_lock); + drop_conf(default_conf); osd_thread_slot = osd_thread_register(dealloc_thread_osd); } @@ -2120,6 +2649,7 @@ mac_do_destroy(struct mac_policy_conf *mpc) */ osd_thread_deregister(osd_thread_slot); osd_jail_deregister(osd_jail_slot); + rm_destroy(&mac_do_rml); } static struct mac_policy_ops do_ops = { diff --git a/sys/sys/imgact.h b/sys/sys/imgact.h index c1c94a2eabfd..51cda4406cad 100644 --- a/sys/sys/imgact.h +++ b/sys/sys/imgact.h @@ -57,6 +57,7 @@ struct image_args { struct image_params { struct proc *proc; /* our process */ + struct thread *td; struct label *execlabel; /* optional exec label */ struct vnode *vp; /* pointer to vnode of file to exec */ struct vm_object *object; /* The vm object for this vp */ diff --git a/sys/sys/signal.h b/sys/sys/signal.h index 863b981c2b7a..792087f735a1 100644 --- a/sys/sys/signal.h +++ b/sys/sys/signal.h @@ -307,8 +307,8 @@ struct __siginfo32 { #define SEGV_ACCERR 2 /* Invalid permissions for mapped */ /* object. */ #define SEGV_PKUERR 100 /* x86: PKU violation */ -#define SEGV_MTEAERR 100 /* arm64: Asynchronous Arm MTE error */ -#define SEGV_MTESERR 101 /* arm64: Synchronous Arm MTE error */ +#define SEGV_MTEAERR 200 /* arm64: Asynchronous Arm MTE error */ +#define SEGV_MTESERR 201 /* arm64: Synchronous Arm MTE error */ /* codes for SIGFPE */ #define FPE_INTOVF 1 /* Integer overflow. */ diff --git a/sys/sys/systm.h b/sys/sys/systm.h index 7f655b48ba08..88c25f06e0cb 100644 --- a/sys/sys/systm.h +++ b/sys/sys/systm.h @@ -554,6 +554,14 @@ void intr_prof_stack_use(struct thread *td, struct trapframe *frame); void counted_warning(unsigned *counter, const char *msg); /* + * Safely read one byte of kernel memory at address addr, placing the + * value into *valp. Returns 0 on success, EFAULT if read was + * impossible, e.g. due to the address not being mapped or not having + * necessary permissions. + */ +int safe_read(vm_offset_t addr, char *valp); + +/* * APIs to manage deprecation and obsolescence. */ void _gone_in(int major, const char *msg, ...) __printflike(2, 3); diff --git a/sys/x86/x86/ucode.c b/sys/x86/x86/ucode.c index 72133de211f8..3d7008eb30f2 100644 --- a/sys/x86/x86/ucode.c +++ b/sys/x86/x86/ucode.c @@ -80,7 +80,7 @@ static const void *ucode_data; static struct ucode_ops *ucode_loader; /* Variables used for reporting success or failure. */ -enum { +static enum { NO_ERROR, NO_MATCH, VERIFICATION_FAILED, @@ -204,7 +204,6 @@ ucode_intel_match(const uint8_t *data, size_t *len) uint64_t platformid; size_t resid; uint32_t data_size, flags, regs[4], sig, total_size; - int i; do_cpuid(1, regs); sig = regs[0]; @@ -226,19 +225,35 @@ ucode_intel_match(const uint8_t *data, size_t *len) if (total_size == 0) total_size = UCODE_INTEL_DEFAULT_DATA_SIZE + sizeof(struct ucode_intel_header); - if (data_size > total_size + sizeof(struct ucode_intel_header)) + + if (total_size > data_size + sizeof(struct ucode_intel_header)) table = (const struct ucode_intel_extsig_table *) ((const uint8_t *)(hdr + 1) + data_size); else table = NULL; - if (hdr->processor_signature == sig) { - if ((hdr->processor_flags & flags) != 0) { - *len = data_size; - return (hdr + 1); + if (hdr->processor_signature == sig && + (hdr->processor_flags & flags) != 0) { + *len = data_size; + return (hdr + 1); + } + if (table != NULL) { + size_t extsize; + + extsize = total_size - + (data_size + sizeof(struct ucode_intel_header)); + if (extsize < sizeof(struct ucode_intel_extsig_table)) { + ucode_error = VERIFICATION_FAILED; + break; } - } else if (table != NULL) { - for (i = 0; i < table->signature_count; i++) { + extsize -= sizeof(struct ucode_intel_extsig_table); + for (uint32_t i = 0; i < table->signature_count; i++) { + if (extsize < sizeof(struct ucode_intel_extsig)) { + ucode_error = VERIFICATION_FAILED; + goto out; + } + extsize -= sizeof(struct ucode_intel_extsig); + entry = &table->entries[i]; if (entry->processor_signature == sig && (entry->processor_flags & flags) != 0) { @@ -248,6 +263,7 @@ ucode_intel_match(const uint8_t *data, size_t *len) } } } +out: return (NULL); } diff --git a/tests/sys/acl/run b/tests/sys/acl/run index f8e9c8d87f71..42dbc7373f7f 100644 --- a/tests/sys/acl/run +++ b/tests/sys/acl/run @@ -105,7 +105,7 @@ if (isatty(fileno(STDOUT))) { } } print $status, "\n"; -exit $failed ? 1 : 0; +exit($failed ? 1 : 0); sub process_test($$$$) { diff --git a/tests/sys/acl/tools-posix.test b/tests/sys/acl/tools-posix.test index 2b2a27d24a0d..aa92911761a6 100644 --- a/tests/sys/acl/tools-posix.test +++ b/tests/sys/acl/tools-posix.test @@ -80,7 +80,7 @@ $ getfacl -qh lll > group::r-x > other::r-x -$ getfacl -q lll +$ getfacl -nq lll > user::rw- > user:42:r-- > group::r-- @@ -89,7 +89,7 @@ $ getfacl -q lll > other::r-- $ setfacl -hm u:44:x,g:45:w lll -$ getfacl -h lll +$ getfacl -hn lll > # file: lll > # owner: root > # group: wheel @@ -111,7 +111,7 @@ $ rm lll # Test removing entries. $ setfacl -x user:42: xxx -$ getfacl xxx +$ getfacl -n xxx > # file: xxx > # owner: root > # group: wheel @@ -369,7 +369,7 @@ $ rm ddd/xxx $ setfacl -dm u::rwx,g::rx,o::rx,mask::rwx ddd $ setfacl -dm g:42:rwx,u:43:r ddd -$ getfacl -dq ddd +$ getfacl -dnq ddd > user::rwx > user:43:r-- > group::r-x @@ -378,7 +378,7 @@ $ getfacl -dq ddd > other::r-x $ touch ddd/xxx -$ getfacl -q ddd/xxx +$ getfacl -nq ddd/xxx > user::rw- > user:43:r-- > group::r-x # effective: r-- @@ -387,7 +387,7 @@ $ getfacl -q ddd/xxx > other::r-- $ mkdir ddd/ddd -$ getfacl -q ddd/ddd +$ getfacl -nq ddd/ddd > user::rwx > user:43:r-- > group::r-x @@ -405,7 +405,7 @@ $ ls -l fff | cut -d' ' -f1 > prw-r--r-- $ setfacl -m u:42:r,g:43:w fff -$ getfacl fff +$ getfacl -n fff > # file: fff > # owner: root > # group: wheel diff --git a/tests/sys/kern/ptrace_test.c b/tests/sys/kern/ptrace_test.c index c1a5d226e990..3a55a6f48033 100644 --- a/tests/sys/kern/ptrace_test.c +++ b/tests/sys/kern/ptrace_test.c @@ -3614,6 +3614,10 @@ ATF_TC_BODY(ptrace__PT_STEP_with_signal, tc) ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI); REQUIRE_EQ(pl.pl_siginfo.si_signo, SIGABRT); +#if defined(__riscv) + atf_tc_expect_fail("PT_STEP not implemented on riscv, see sys/riscv/riscv/ptrace_machdep.c"); +#endif + /* Step the child process inserting SIGUSR1. */ REQUIRE_EQ(ptrace(PT_STEP, fpid, (caddr_t)1, SIGUSR1), 0); @@ -3731,6 +3735,10 @@ ATF_TC_BODY(ptrace__step_siginfo, tc) ATF_REQUIRE(WIFSTOPPED(status)); REQUIRE_EQ(WSTOPSIG(status), SIGSTOP); +#if defined(__riscv) + atf_tc_expect_fail("PT_STEP not implemented on riscv, see sys/riscv/riscv/ptrace_machdep.c"); +#endif + /* Step the child ignoring the SIGSTOP. */ REQUIRE_EQ(ptrace(PT_STEP, fpid, (caddr_t)1, 0), 0); diff --git a/tests/sys/mac/do/Makefile b/tests/sys/mac/do/Makefile index 980067ea56e6..0c40f65b65f6 100644 --- a/tests/sys/mac/do/Makefile +++ b/tests/sys/mac/do/Makefile @@ -2,13 +2,12 @@ PACKAGE= tests TESTSDIR= ${TESTSBASE}/sys/mac/do -ATF_TESTS_SH+= valid_configs invalid_configs +ATF_TESTS_SH+= valid_configs invalid_configs consistency ${PACKAGE}FILES+= common.sh TEST_METADATA+= execenv="jail" TEST_METADATA+= required_kmods="mac_do" TEST_METADATA+= required_user="root" -TEST_METADATA+= required_programs="sysctl" .include <bsd.test.mk> diff --git a/tests/sys/mac/do/common.sh b/tests/sys/mac/do/common.sh index 88529adcc1f3..4f0e838bbf5f 100644 --- a/tests/sys/mac/do/common.sh +++ b/tests/sys/mac/do/common.sh @@ -1,5 +1,6 @@ +# Copyright (c) 2026 The FreeBSD Foundation # -# Copyright (c) 2026, The FreeBSD Foundation +# SPDX-License-Identifier: BSD-2-Clause # # This software was developed by Olivier Certner <olce@FreeBSD.org> at # Kumacom SARL under sponsorship from the FreeBSD Foundation. @@ -9,11 +10,79 @@ rules_parameter() echo "$1".rules } +exec_paths_parameter() +{ + echo "$1".exec_paths +} + +: ${MDO:=/usr/bin/mdo} + +ROOT_KNOB=security.mac.do +RULES_KNOB=$(rules_parameter ${ROOT_KNOB}) +EXEC_PATHS_KNOB=$(exec_paths_parameter ${ROOT_KNOB}) +PPE_KNOB=${ROOT_KNOB}.print_parse_error + +ROOT_JAIL_PARAM=mac.do +RULES_JAIL_PARAM=$(rules_parameter ${ROOT_JAIL_PARAM}) +EXEC_PATHS_JAIL_PARAM=$(exec_paths_parameter ${ROOT_JAIL_PARAM}) + +# To be overridden to execute commands in a sub-jail +JEXEC= + +# Exit status: 0 iff disabled +mac_do_disabled() +{ + [ -z "$($JEXEC sysctl -n ${RULES_KNOB})" ] || + [ -z "$($JEXEC sysctl -n ${EXEC_PATHS_KNOB})" ] +} + +mac_do_check_disabled() +{ + mac_do_disabled || atf_fail "mac_do(4) expected disabled but is not." +} -CONF_ROOT_KNOB=security.mac.do -RULES_KNOB=$(rules_parameter ${CONF_ROOT_KNOB}) -PPE_KNOB=${CONF_ROOT_KNOB}.print_parse_error +mac_do_ensure_disabled() +{ + mac_do_disabled || $JEXEC sysctl ${RULES_KNOB}="" +} +sysctl_rules() +{ + $JEXEC sysctl -n ${RULES_KNOB} +} + +sysctl_exec_paths() +{ + $JEXEC sysctl -n ${EXEC_PATHS_KNOB} +} + +# $1 = sysctl func, $2 = expected value +sysctl_check() +{ + local func value + + func=$1 + value=$2 + atf_check [ "$($func)" = "$value" ] +} + +# $1 = value +sysctl_check_rules() +{ + local value + + value=$1 + sysctl_check sysctl_rules $value +} + +# $1 = value +sysctl_check_exec_paths() +{ + local value + + value=$1 + sysctl_check sysctl_exec_paths $value +} # $1 = knob name, $2 = value sysctl_set_and_check() @@ -22,8 +91,8 @@ sysctl_set_and_check() knob=$1 value=$2 - atf_check -o ignore sysctl "$knob"="$value" - atf_check -o inline:"$value\n" sysctl -n "$knob" + atf_check -o ignore $JEXEC sysctl "$knob"="$value" + atf_check -o inline:"$value\n" $JEXEC sysctl -n "$knob" } # $1 = knob name, $2 = value @@ -34,8 +103,8 @@ sysctl_set_and_check_fails() knob=$1 value=$2 orig_value=$(sysctl -n "$knob") - atf_check -s not-exit:0 -o ignore -e ignore sysctl "$knob"="$value" - atf_check -o inline:"${orig_value}\n" sysctl -n "$knob" + atf_check -s not-exit:0 -o ignore -e ignore $JEXEC sysctl "$knob"="$value" + atf_check -o inline:"${orig_value}\n" $JEXEC sysctl -n "$knob" } # $1 = sysctl function, $2 = value @@ -45,9 +114,9 @@ sysctl_set_and_check_rules_common() func=$1 value=$2 - "$func" ${RULES_KNOB} "$value" - # Same spec but using the older in-rule separator (':') + # Use older in-rule separator (':') first to have final value as specified "$func" ${RULES_KNOB} "$(echo "$value" | sed 's%>%:%')" + "$func" ${RULES_KNOB} "$value" } # $1 = value @@ -68,5 +137,40 @@ sysctl_set_and_check_fails_rules() sysctl_set_and_check_rules_common sysctl_set_and_check_fails "$value" } +# $1 = sysctl function, $2 = value +sysctl_set_and_check_exec_paths_common() +{ + local func value + + func=$1 + value=$2 + # Use older in-rule separator (':') first to have final value as specified + "$func" ${EXEC_PATHS_KNOB} "$(echo "$value" | sed 's%>%:%')" + "$func" ${EXEC_PATHS_KNOB} "$value" +} + +# $1 = value +sysctl_set_and_check_exec_paths() +{ + local value + + value=$1 + sysctl_set_and_check_exec_paths_common sysctl_set_and_check "$value" +} + +# Create a persistent subjail. Echoes its JID. +launch_subjail() +{ + ( + set -o pipefail + $JEXEC jail -c -J /dev/stdout persist=true | + sed -nE 's%^.*jid=([0-9]+).*$%\1%p' + ) || atf_fail "Cannot create a subjail (check children limits?)" +} + +atf_require_prog sysctl +atf_require_prog jail +atf_require_prog sed + # Do not pollute kernel logs with parse errors sysctl $PPE_KNOB=0 >/dev/null 2>&1 diff --git a/tests/sys/mac/do/consistency.sh b/tests/sys/mac/do/consistency.sh new file mode 100644 index 000000000000..6a64917edb6d --- /dev/null +++ b/tests/sys/mac/do/consistency.sh @@ -0,0 +1,211 @@ +# Copyright (c) 2026 The FreeBSD Foundation +# +# SPDX-License-Identifier: BSD-2-Clause +# +# This software was developed by Olivier Certner <olce@FreeBSD.org> at +# Kumacom SARL under sponsorship from the FreeBSD Foundation. + +SJ_JID_FILE=sj.jid + +atf_test_case concurrent_rules_exec_paths_changes +concurrent_rules_exec_paths_changes_head() +{ + atf_set descr "Consistency of rules and exec paths changes on same jail" +} +concurrent_rules_exec_paths_changes_body() +{ + local rules exec_paths rules_es exec_paths_es + + for I in $(jot - 1 1000); do + sysctl_set_and_check_rules "uid=$I>uid=1001" + done & + rules=$! + + for I in $(jot - 1 1000); do + sysctl_set_and_check_exec_paths /nowhere/nonexistent$I + done & + exec_paths=$! + + wait $rules + rules_es=$? + + wait $exec_paths + exec_paths_es=$? + + # atf_check called in the asynchronous AND-OR lists above causes exit of the + # subshells and also a write to the ATF result file. These writes are + # concurrent and may cause the result file to be malformed. Consequently, + # it is important that, once execution becomes sequential again, atf_fail() is + # called again (and not just exit()). + if [ $rules_es -ne 0 ] || [ $exec_paths_es -ne 0 ]; then + atf_fail "Rules exit status: $rules_es, \ +exec paths exit status: $exec_paths_es" + fi +} + +atf_test_case inheritance cleanup +inheritance_head() +{ + atf_set descr "Simple inheritance test (values propagated to child jail)" +} +inheritance_body() +{ + local sj rules exec_paths + + # For the sake of not running the test under Kyua + mac_do_ensure_disabled + + sj=$(launch_subjail) + echo $sj > "${SJ_JID_FILE}" + + jail -m jid=$sj ${ROOT_JAIL_PARAM}=inherit + JEXEC="jexec $sj" + mac_do_check_disabled + JEXEC= + + rules="uid=1001>uid=0" + sysctl_set_and_check_rules $rules + JEXEC="jexec $sj" + sysctl_check_rules $rules + JEXEC= + + rules="gid=1001>uid=0" + sysctl_set_and_check_rules $rules + JEXEC="jexec $sj" + sysctl_check_rules $rules + JEXEC= + + # Not really necessary, just to keep mac_do(4) disabled + sysctl_set_and_check_rules "" + + exec_paths="/nowhere/nonexistent" + sysctl_set_and_check_exec_paths $exec_paths + JEXEC="jexec $sj" + sysctl_check_exec_paths $exec_paths + JEXEC= + + exec_paths="$MDO" + sysctl_set_and_check_exec_paths $exec_paths + JEXEC="jexec $sj" + sysctl_check_exec_paths $exec_paths + JEXEC= +} +inheritance_cleanup() +{ + # We clean up our subjail manually just for the sake of launching this test + # with atf-sh. Kyua is informed that these tests should run in a jail, and + # kills it automatically after the test, which kills all subjails. It is + # annoying that atf-sh does not offer a more practical way to pass + # information from the body to the cleanup part than a file. + jail -r $(cat "${SJ_JID_FILE}") + rm -f "${SJ_JID_FILE}" +} + +atf_test_case inheritance_relax_parent_jail cleanup +inheritance_relax_parent_jail_head() +{ + atf_set descr \ + "Test sequential consistency in a \"relax parent rules\" scenario" +} +inheritance_relax_parent_jail_body() +{ + local sj rules exec_paths subproc + + sj=$(launch_subjail) + echo $sj > "${SJ_JID_FILE}" + + jail -m jid=$sj ${ROOT_JAIL_PARAM}=inherit + rules="uid=1001>uid=0" + sysctl_set_and_check_rules $rules + # Additional inheritance sanity check + JEXEC="jexec $sj" + sysctl_check_rules $rules + JEXEC= + exec_paths="$MDO" + sysctl_set_and_check_exec_paths $exec_paths + # Additional inheritance sanity check + JEXEC="jexec $sj" + sysctl_check_exec_paths $exec_paths + JEXEC= + + # Launch a process that tries to become 'root' from user 1002, and verify + # that this always fails. + { for I in $(jot - 1 1000); do + jexec $sj "$MDO" -u 1002 -g 1002 -G 1002 "$MDO" -i true 2>/dev/null && + exit 1 + done; true; } & + subproc=$! + + # Decouple the subjail from the parent jail, copying its parameters + jail -m jid=$sj ${ROOT_JAIL_PARAM}=new + # Allow user 1002 to become 'root' on the parent jail + sysctl_set_and_check_rules "$rules;uid=1002>uid=0" + JEXEC="jexec $sj" + # Additional sanity check (that rules of the subjail are now independent) + [ "$(sysctl_rules)" == $rules ] || atf_fail "Rules not copied" + [ "$(sysctl_exec_paths)" == $exec_paths ] || + atf_fail "Exec paths not copied" + JEXEC= + + wait $subproc || atf_fail "A transition wrongly succeeded in the subjail!" +} +inheritance_relax_parent_jail_cleanup() +{ + # See inheritance_cleanup() for explanations + jail -r $(cat "${SJ_JID_FILE}") + rm -f "${SJ_JID_FILE}" +} + +atf_test_case same_knob_and_jail_parameter cleanup +same_knob_and_jail_parameter_head() +{ + atf_set descr \ + "Corresponding sysctl knobs and jail parameters have same value" +} +same_knob_and_jail_parameter_body() +{ + local sj rules exec_paths subproc + + sj=$(launch_subjail) + echo $sj > "${SJ_JID_FILE}" + + # Set sysctl knobs, observe parameters + rules="uid=19999>uid=21700" + exec_paths="/improbable/path/he" + JEXEC="jexec $sj" + sysctl_set_and_check_rules $rules + sysctl_set_and_check_exec_paths $exec_paths + JEXEC= + atf_check -o inline:"$rules\n" jls -j $sj ${RULES_JAIL_PARAM} + atf_check -o inline:"${exec_paths}\n" jls -j $sj ${EXEC_PATHS_JAIL_PARAM} + + # Set parameters, observe knobs + rules="uid=128000>uid=-1" + exec_paths="/hello/i_ve/changed" + jail -m jid=$sj ${RULES_JAIL_PARAM}=$rules \ + ${EXEC_PATHS_JAIL_PARAM}=${exec_paths} + JEXEC="jexec $sj" + sysctl_check_rules $rules + sysctl_check_exec_paths $exec_paths + JEXEC= +} +same_knob_and_jail_parameter_cleanup() +{ + # See inheritance_cleanup() for explanations + jail -r $(cat "${SJ_JID_FILE}") + rm -f "${SJ_JID_FILE}" +} + + +atf_init_test_cases() +{ + . $(atf_get_srcdir)/common.sh + atf_require_prog jot + # Needs an absolute path for mdo(1), to set it in exec_paths + atf_require_prog "$MDO" + + atf_add_test_case concurrent_rules_exec_paths_changes + atf_add_test_case inheritance + atf_add_test_case inheritance_relax_parent_jail + atf_add_test_case same_knob_and_jail_parameter +} diff --git a/tests/sys/mac/do/invalid_configs.sh b/tests/sys/mac/do/invalid_configs.sh index f24309cb2f3b..d1a9eb8c1e96 100644 --- a/tests/sys/mac/do/invalid_configs.sh +++ b/tests/sys/mac/do/invalid_configs.sh @@ -1,6 +1,6 @@ -#!/usr/bin/env atf-sh +# Copyright (c) 2026 The FreeBSD Foundation # -# Copyright (c) 2026, The FreeBSD Foundation +# SPDX-License-Identifier: BSD-2-Clause # # This software was developed by Olivier Certner <olce@FreeBSD.org> at # Kumacom SARL under sponsorship from the FreeBSD Foundation. @@ -75,7 +75,7 @@ rules_wrong_separator_body() atf_init_test_cases() { - . $(atf_get_srcdir)/common.sh + . "$(atf_get_srcdir)"/common.sh atf_add_test_case rule_no_target_part atf_add_test_case rule_no_match_part diff --git a/tests/sys/mac/do/valid_configs.sh b/tests/sys/mac/do/valid_configs.sh index bd5b53b5d5d8..fc1c9a370854 100644 --- a/tests/sys/mac/do/valid_configs.sh +++ b/tests/sys/mac/do/valid_configs.sh @@ -1,6 +1,6 @@ -#!/usr/bin/env atf-sh +# Copyright (c) 2026 The FreeBSD Foundation # -# Copyright (c) 2026, The FreeBSD Foundation +# SPDX-License-Identifier: BSD-2-Clause # # This software was developed by Olivier Certner <olce@FreeBSD.org> at # Kumacom SARL under sponsorship from the FreeBSD Foundation. @@ -120,7 +120,7 @@ gid= 1001 >gid =5" atf_init_test_cases() { - . $(atf_get_srcdir)/common.sh + . "$(atf_get_srcdir)"/common.sh atf_add_test_case rule_uid_to_any atf_add_test_case rule_uid_to_uid diff --git a/tests/sys/netipsec/tunnel/Makefile b/tests/sys/netipsec/tunnel/Makefile index c6060a790cc3..49fddc403005 100644 --- a/tests/sys/netipsec/tunnel/Makefile +++ b/tests/sys/netipsec/tunnel/Makefile @@ -13,8 +13,8 @@ ATF_TESTS_SH+= empty \ aesni_aes_gcm_256 \ chacha20_poly1305 -# Each test uses the same names for its jails, so they must be run serially. -TEST_METADATA+= is_exclusive=true +TEST_METADATA+= execenv="jail" \ + execenv_jail_params="vnet allow.raw_sockets" ${PACKAGE}FILES+= utils.subr diff --git a/tools/test/stress2/misc/all.exclude b/tools/test/stress2/misc/all.exclude index 9ec5bffde0f6..ef8cb69cd241 100644 --- a/tools/test/stress2/misc/all.exclude +++ b/tools/test/stress2/misc/all.exclude @@ -39,6 +39,7 @@ mount7.sh https://people.freebsd.org/~pho/stress/log/log0549.txt 20240912 mlockall2.sh Unrecoverable OOM killing seen 20190203 mlockall6.sh https://people.freebsd.org/~pho/stress/log/log0430.txt 20230403 mlockall7.sh Needs further investigation 20210123 +msdos24.sh Waiting for fix 20260529 msetdomain.sh May change policy for random threads to domainset_fixed 20210104 newfs4.sh watchdog fired. newbuf (still seen 20240729) 20190225 nfs10.sh Double fault 20151013 diff --git a/tools/test/stress2/misc/msdos22.sh b/tools/test/stress2/misc/msdos22.sh new file mode 100755 index 000000000000..f3a2110f13f1 --- /dev/null +++ b/tools/test/stress2/misc/msdos22.sh @@ -0,0 +1,77 @@ +#!/bin/sh + +# Test file operations using long random file names consisting only of ASCII characters + +MDUNIT=10 +FS=/mnt +LOCALE=C +FILES=1000 + +export LANG=$LOCALE + +randomfilename () { + name="" + count=$(jot -r 1 10 3) + for r in $(jot -r $count 7 0); do + r=$(( r + 0 )) + c='_' + if [ $r -gt 0 ]; then + for i in $(jot $r); do + name="$name$i" + done + fi + count=$(( count - 1 )) + if [ "$count" -gt 0 ]; then + name="$name$c" + fi + done + echo "$name" +} + +( + set -e + + mdconfig -u $MDUNIT -t malloc -s 512m + newfs_msdos -c 8 -F 32 /dev/md$MDUNIT > /dev/null 2>&1 + mkdir -p $FS + mount_msdosfs /dev/md$MDUNIT $FS + + mkdir -p $FS/test + cd $FS/test + + for i in $(jot $FILES); do + testfiles="$testfiles +$(randomfilename)" + done + + testfiles=$(echo "$testfiles" | grep "." | sort -R | uniq) + + for f in $testfiles; do + echo "$f" > $f + done + for f in $(echo "$testfiles" | sort -R); do + cp $f $f.tmp + done + for f in $(echo "$testfiles" | sort -R); do + mv $f.tmp $f + done + for f in $(echo "$testfiles" | sort -R); do + rm $f + done +) + +failed=$? + +cd + +[ "$failed" -ne 0 ] && ls $FS/test + +umount /dev/md$MDUNIT + +#[ "$failed" -ne 0 ] && hd /dev/md$MDUNIT > /tmp/msdos22.dump + +fsck_msdosfs -y /dev/md$MDUNIT + +mdconfig -d -u $MDUNIT 2>/dev/null + +exit $failed diff --git a/tools/test/stress2/misc/msdos23.sh b/tools/test/stress2/misc/msdos23.sh new file mode 100755 index 000000000000..fcaa90917235 --- /dev/null +++ b/tools/test/stress2/misc/msdos23.sh @@ -0,0 +1,77 @@ +#!/bin/sh + +# Test file operations using random file names containing non-ASCII characters + +MDUNIT=10 +FS=/mnt +LOCALE=C.UTF-8 +FILES=1000 + +export LANG=$LOCALE + +randomfilename () { + name="" + count=$(jot -r 1 10 3) + for r in $(jot -r $count 7 0); do + r=$(( r + 0 )) + c='ยท' + if [ $r -gt 0 ]; then + for i in $(jot $r); do + name="$name$i" + done + fi + count=$(( count - 1 )) + if [ "$count" -gt 0 ]; then + name="$name$c" + fi + done + echo "$name" +} + +( + set -e + + mdconfig -u $MDUNIT -t malloc -s 512m + newfs_msdos -c 8 -F 32 /dev/md$MDUNIT > /dev/null 2>&1 + mkdir -p $FS + mount_msdosfs -L $LOCALE /dev/md$MDUNIT $FS + + mkdir -p $FS/test + cd $FS/test + + for i in $(jot $FILES); do + testfiles="$testfiles +$(randomfilename)" + done + + testfiles=$(echo "$testfiles" | grep "." | sort -R | uniq) + + for f in $testfiles; do + echo "$f" > $f + done + for f in $(echo "$testfiles" | sort -R); do + cp $f $f.tmp + done + for f in $(echo "$testfiles" | sort -R); do + mv $f.tmp $f + done + for f in $(echo "$testfiles" | sort -R); do + rm $f + done +) + +failed=$? + +cd + +[ "$failed" -ne 0 ] && ls $FS/test + +umount /dev/md$MDUNIT + +#[ "$failed" -ne 0 ] && hd /dev/md$MDUNIT > /tmp/msdos23.dump + +fsck_msdosfs -y /dev/md$MDUNIT + +mdconfig -d -u $MDUNIT 2>/dev/null + +exit $failed diff --git a/tools/test/stress2/misc/msdos24.sh b/tools/test/stress2/misc/msdos24.sh new file mode 100755 index 000000000000..edb524293c0c --- /dev/null +++ b/tools/test/stress2/misc/msdos24.sh @@ -0,0 +1,78 @@ +#!/bin/sh + +# Test file operations using long random file names containing UTF-16 surrogate pairs + +MDUNIT=10 +FS=/mnt +LOCALE=C.UTF-8 +FILES=1000 + +export LANG=$LOCALE + +randomfilename () { + name="" + count=$(jot -r 1 10 3) + for r in $(jot -r $count 7 0); do + r=$(( r + 0 )) + emoji="\0360\0237\0230\020$r" + c=$(echo -e $emoji) + if [ $r -gt 0 ]; then + for i in $(jot $r); do + name="$name$i" + done + fi + count=$(( count - 1 )) + if [ "$count" -gt 0 ]; then + name="$name$c" + fi + done + echo "$name" +} + +( + set -e + + mdconfig -u $MDUNIT -t malloc -s 512m + newfs_msdos -c 8 -F 32 /dev/md$MDUNIT > /dev/null 2>&1 + mkdir -p $FS + mount_msdosfs -L $LOCALE /dev/md$MDUNIT $FS + + mkdir -p $FS/test + cd $FS/test + + for i in $(jot $FILES); do + testfiles="$testfiles +$(randomfilename)" + done + + testfiles=$(echo "$testfiles" | grep "." | sort -R | uniq) + + for f in $testfiles; do + echo "$f" > $f + done + for f in $(echo "$testfiles" | sort -R); do + cp $f $f.tmp + done + for f in $(echo "$testfiles" | sort -R); do + mv $f.tmp $f + done + for f in $(echo "$testfiles" | sort -R); do + rm $f + done +) + +failed=$? + +cd + +[ "$failed" -ne 0 ] && ls $FS/test + +umount /dev/md$MDUNIT + +#[ "$failed" -ne 0 ] && hd /dev/md$MDUNIT > /tmp/msdos24.dump + +fsck_msdosfs -y /dev/md$MDUNIT + +mdconfig -d -u $MDUNIT 2>/dev/null + +exit $failed diff --git a/usr.bin/cap_mkdb/cap_mkdb.c b/usr.bin/cap_mkdb/cap_mkdb.c index 7ee6d2ddd2b3..019dad1ee72e 100644 --- a/usr.bin/cap_mkdb/cap_mkdb.c +++ b/usr.bin/cap_mkdb/cap_mkdb.c @@ -117,6 +117,7 @@ main(int argc, char *argv[]) if (capdbp->close(capdbp) < 0) err(1, "%s", capname); + free(capname); capname = NULL; exit(0); } @@ -151,7 +152,7 @@ db_build(char **ifiles) data.data = NULL; key.data = NULL; - for (reccnt = 0, bplen = 0; (st = cgetnext(&bp, ifiles)) > 0;) { + for (reccnt = 0, bplen = 0; (st = cgetnext(&bp, ifiles)) > 0; free(bp)) { /* * Allocate enough memory to store record, terminating diff --git a/usr.bin/xinstall/Makefile b/usr.bin/xinstall/Makefile index fd95b97160fe..c05a50420c82 100644 --- a/usr.bin/xinstall/Makefile +++ b/usr.bin/xinstall/Makefile @@ -11,7 +11,7 @@ MAN= install.1 CFLAGS+= -I${SRCTOP}/contrib/mtree CFLAGS+= -I${SRCTOP}/lib/libnetbsd -LIBADD= md +LIBADD= md util CFLAGS+= -DWITH_MD5 -DWITH_RIPEMD160 .ifdef BOOTSTRAPPING diff --git a/usr.bin/xinstall/install.1 b/usr.bin/xinstall/install.1 index c923321f20fe..169bf4ef11fe 100644 --- a/usr.bin/xinstall/install.1 +++ b/usr.bin/xinstall/install.1 @@ -33,7 +33,7 @@ .Nd install binaries .Sh SYNOPSIS .Nm -.Op Fl bCcpSsUv +.Op Fl bCcpSsUvz .Op Fl B Ar suffix .Op Fl D Ar destdir .Op Fl f Ar flags @@ -45,9 +45,10 @@ .Op Fl N Ar dbdir .Op Fl o Ar owner .Op Fl T Ar tags +.Op Fl z Ar size .Ar file1 file2 .Nm -.Op Fl bCcpSsUv +.Op Fl bCcpSsUvz .Op Fl B Ar suffix .Op Fl D Ar destdir .Op Fl f Ar flags @@ -59,6 +60,7 @@ .Op Fl N Ar dbdir .Op Fl o Ar owner .Op Fl T Ar tags +.Op Fl z Ar size .Ar file1 ... fileN directory .Nm .Fl d @@ -264,6 +266,13 @@ Cause .Nm to be verbose, showing files as they are installed or backed up. +.It Fl z Ar maxsize +Limit the comparison feature of +.Fl C +to files no larger than +.Ar maxsize . +Files exceeding this limit bypass the comparison step and are directly overwritten. +The default maximum size is 128MiB. .El .Pp By default, diff --git a/usr.bin/xinstall/xinstall.c b/usr.bin/xinstall/xinstall.c index 1aed8c1b24e4..d389bdbe3737 100644 --- a/usr.bin/xinstall/xinstall.c +++ b/usr.bin/xinstall/xinstall.c @@ -57,6 +57,7 @@ #include <string.h> #include <sysexits.h> #include <unistd.h> +#include <util.h> #include <vis.h> #include "mtree.h" @@ -87,7 +88,7 @@ #define HAVE_STRUCT_STAT_ST_FLAGS 0 #endif -#define MAX_CMP_SIZE (16 * 1024 * 1024) +#define MAX_CMP_SIZE (128 * 1024 * 1024) #define LN_ABSOLUTE 0x01 #define LN_RELATIVE 0x02 @@ -137,6 +138,7 @@ static FILE *metafp; static const char *group, *owner; static const char *suffix = BACKUP_SUFFIX; static char *destdir, *digest, *fflags, *metafile, *tags; +static size_t max_compare_size = MAX_CMP_SIZE; static int compare(int, const char *, size_t, int, const char *, size_t, char **); @@ -168,12 +170,13 @@ main(int argc, char *argv[]) u_int iflags; char *p; const char *to_name; + uint64_t num; fset = 0; iflags = 0; set = NULL; group = owner = NULL; - while ((ch = getopt(argc, argv, "B:bCcD:df:g:h:l:M:m:N:o:pSsT:Uv")) != + while ((ch = getopt(argc, argv, "B:bCcD:df:g:h:l:M:m:N:o:pSsT:Uvz:")) != -1) switch((char)ch) { case 'B': @@ -270,6 +273,13 @@ main(int argc, char *argv[]) case 'v': verbose = 1; break; + case 'z': + if (expand_number(optarg, &num) != 0 || num == 0) { + errx(EX_USAGE, "invalid max compare filesize:" + " %s", optarg); + } + max_compare_size = num; + break; case '?': default: usage(); @@ -1092,7 +1102,7 @@ compare(int from_fd, const char *from_name __unused, size_t from_len, do_digest = (digesttype != DIGEST_NONE && dresp != NULL && *dresp == NULL); - if (from_len <= MAX_CMP_SIZE) { + if (from_len <= max_compare_size) { static char *buf, *buf1, *buf2; static size_t bufsize; int n1, n2; @@ -1484,11 +1494,11 @@ usage(void) { (void)fprintf(stderr, "usage: install [-bCcpSsUv] [-f flags] [-g group] [-m mode] [-o owner]\n" -" [-M log] [-D dest] [-h hash] [-T tags]\n" +" [-M log] [-D dest] [-h hash] [-T tags] [-z maxcmpsize]\n" " [-B suffix] [-l linkflags] [-N dbdir]\n" " file1 file2\n" " install [-bCcpSsUv] [-f flags] [-g group] [-m mode] [-o owner]\n" -" [-M log] [-D dest] [-h hash] [-T tags]\n" +" [-M log] [-D dest] [-h hash] [-T tags] [-z maxcmpsize]\n" " [-B suffix] [-l linkflags] [-N dbdir]\n" " file1 ... fileN directory\n" " install -dU [-vU] [-g group] [-m mode] [-N dbdir] [-o owner]\n" diff --git a/usr.sbin/bsdinstall/distextract/distextract.c b/usr.sbin/bsdinstall/distextract/distextract.c index 32bd9453eb80..35cf19aae33f 100644 --- a/usr.sbin/bsdinstall/distextract/distextract.c +++ b/usr.sbin/bsdinstall/distextract/distextract.c @@ -291,6 +291,8 @@ extract_files(struct bsddialog_fileminibar *file) /* If that went well, perform the extraction */ if (retval == ARCHIVE_OK) retval = archive_read_extract(archive, entry, + ARCHIVE_EXTRACT_SECURE_NODOTDOT | + ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS | ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_OWNER | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL | ARCHIVE_EXTRACT_XATTR | ARCHIVE_EXTRACT_FFLAGS); diff --git a/usr.sbin/bsdinstall/scripts/script b/usr.sbin/bsdinstall/scripts/script index 93d07c7899c3..4c792d80df6a 100755 --- a/usr.sbin/bsdinstall/scripts/script +++ b/usr.sbin/bsdinstall/scripts/script @@ -50,6 +50,7 @@ f_include $BSDCFG_SHARE/variable.subr ############################################################ GLOBALS : ${TMPDIR:="/tmp"} +: ${DISTRIBUTIONS=""}; export DISTRIBUTIONS # # Strings that should be moved to an i18n file and loaded with f_include_lang() diff --git a/usr.sbin/certctl/certctl.c b/usr.sbin/certctl/certctl.c index 0a07703bf37b..462f6c1730a9 100644 --- a/usr.sbin/certctl/certctl.c +++ b/usr.sbin/certctl/certctl.c @@ -1093,6 +1093,7 @@ int main(int argc, char *argv[]) { const char *command; + unsigned int i; int opt; while ((opt = getopt(argc, argv, "BcD:d:g:lL:M:no:Uv")) != -1) @@ -1155,8 +1156,8 @@ main(int argc, char *argv[]) set_defaults(); - for (unsigned i = 0; commands[i].name != NULL; i++) + for (i = 0; commands[i].name != NULL; i++) if (strcmp(command, commands[i].name) == 0) - exit(!!commands[i].func(argc, argv)); + exit(commands[i].func(argc, argv) == 0 ? 0 : 1); usage(); } diff --git a/usr.sbin/crashinfo/crashinfo.sh b/usr.sbin/crashinfo/crashinfo.sh index 68115f09f9d4..87e5565b98e3 100755 --- a/usr.sbin/crashinfo/crashinfo.sh +++ b/usr.sbin/crashinfo/crashinfo.sh @@ -149,11 +149,13 @@ fi VMCORE=$CRASHDIR/vmcore.$DUMPNR INFO=$CRASHDIR/info.$DUMPNR FILE=$CRASHDIR/core.txt.$DUMPNR +LINK=$CRASHDIR/core.txt.last HOSTNAME=`hostname` if $BATCH; then echo "Writing crash summary to $FILE." exec > $FILE 2>&1 + ln -sf $FILE $LINK fi GDB=/usr/local/bin/gdb @@ -204,6 +206,7 @@ machine=$(gdb_command $KERNEL 'printf "%s", machine') if ! $BATCH; then echo "Writing crash summary to $FILE." exec > $FILE 2>&1 + ln -sf $FILE $LINK fi echo "$HOSTNAME dumped core - see $VMCORE" diff --git a/usr.sbin/ctld/ctld.cc b/usr.sbin/ctld/ctld.cc index 9bdf15976911..834bef4ef363 100644 --- a/usr.sbin/ctld/ctld.cc +++ b/usr.sbin/ctld/ctld.cc @@ -1175,21 +1175,12 @@ conf::add_port(struct target *target, struct pport *pp) return (false); } - pp->link(); return (true); } bool -conf::add_port(struct kports &kports, struct target *target, int pp, int vp) +conf::add_port(struct target *target, const std::string &pname, int pp, int vp) { - struct pport *pport; - - std::string pname = freebsd::stringf("ioctl/%d/%d", pp, vp); - - pport = kports.find_port(pname); - if (pport != NULL) - return (add_port(target, pport)); - std::string name = pname + "-" + target->name(); const auto &pair = conf_ports.try_emplace(name, std::make_unique<ioctl_port>(target, pp, vp)); @@ -1387,6 +1378,19 @@ target::set_auth_type(const char *type) bool target::add_physical_port(std::string_view pport) { + /* Normalize ioctl port names. */ + std::string pname; + if (pport.compare(0, strlen("ioctl/"), "ioctl/") == 0) { + int ret, pp, vp; + + pname = std::string(pport); + ret = sscanf(pname.c_str(), "ioctl/%d/%d", &pp, &vp); + if (ret == 2) { + pname = freebsd::stringf("ioctl/%d/%d", pp, vp); + pport = pname; + } + } + for (const auto &s : t_pports) { if (s == pport) { log_warnx("duplicate physical port \"%s\" for target " @@ -2636,6 +2640,7 @@ conf_new_from_file(const char *path, bool ucl) bool conf::add_pports(struct kports &kports) { + std::unordered_map<struct pport *, struct target *> linked_ports; struct pport *pp; int ret, i_pp, i_vp; @@ -2643,35 +2648,50 @@ conf::add_pports(struct kports &kports) struct target *targ = kv.second.get(); for (const auto &pport : targ->pports()) { - ret = sscanf(pport.c_str(), "ioctl/%d/%d", &i_pp, - &i_vp); - if (ret > 0) { - if (!add_port(kports, targ, i_pp, i_vp)) { - log_warnx("can't create new ioctl port " - "for %s", targ->label()); + /* + * If this port is already present in the + * kernel, reuse the existing port. + */ + pp = kports.find_port(pport); + if (pp != nullptr) { + const auto &pair = linked_ports.try_emplace(pp, + targ); + if (!pair.second) { + log_warnx("can't link port \"%s\" to " + "%s, port already linked to %s", + pport.c_str(), targ->label(), + pair.first->second->label()); return (false); } + if (!add_port(targ, pp)) { + log_warnx( + "can't link port \"%s\" to %s", + pport.c_str(), targ->label()); + return (false); + } continue; } - pp = kports.find_port(pport); - if (pp == NULL) { - log_warnx("unknown port \"%s\" for %s", - pport.c_str(), targ->label()); - return (false); - } - if (pp->linked()) { - log_warnx("can't link port \"%s\" to %s, " - "port already linked to some target", - pport.c_str(), targ->label()); - return (false); - } - if (!add_port(targ, pp)) { - log_warnx("can't link port \"%s\" to %s", - pport.c_str(), targ->label()); - return (false); + /* + * If this port is an ioctl port, create a new + * port. + */ + ret = sscanf(pport.c_str(), "ioctl/%d/%d", &i_pp, + &i_vp); + if (ret == 2) { + if (!add_port(targ, pport, i_pp, i_vp)) { + log_warnx("can't create new port %s " + "for %s", pport.c_str(), + targ->label()); + return (false); + } + continue; } + + log_warnx("unknown port \"%s\" for %s", + pport.c_str(), targ->label()); + return (false); } } return (true); diff --git a/usr.sbin/ctld/ctld.hh b/usr.sbin/ctld/ctld.hh index 7ae033804157..3bc92449e372 100644 --- a/usr.sbin/ctld/ctld.hh +++ b/usr.sbin/ctld/ctld.hh @@ -487,7 +487,7 @@ struct conf { bool add_port(struct target *target, struct portal_group *pg, uint32_t ctl_port); bool add_port(struct target *target, struct pport *pp); - bool add_port(struct kports &kports, struct target *target, int pp, + bool add_port(struct target *target, const std::string &pname, int pp, int vp); bool add_pports(struct kports &kports); @@ -567,13 +567,9 @@ struct pport { const char *name() const { return pp_name.c_str(); } uint32_t ctl_port() const { return pp_ctl_port; } - bool linked() const { return pp_linked; } - void link() { pp_linked = true; } - private: std::string pp_name; uint32_t pp_ctl_port; - bool pp_linked = false; }; struct kports { diff --git a/usr.sbin/ctld/kernel.cc b/usr.sbin/ctld/kernel.cc index a6b0a79850ec..ef7ef87af090 100644 --- a/usr.sbin/ctld/kernel.cc +++ b/usr.sbin/ctld/kernel.cc @@ -446,8 +446,8 @@ add_iscsi_port(struct kports &kports, struct conf *conf, const struct cctl_port &port, std::string &name) { if (port.cfiscsi_target.empty()) { - log_debugx("CTL port %u \"%s\" wasn't managed by ctld; ", - port.port_id, name.c_str()); + log_debugx("CTL iSCSI port %u \"%s\" is not managed by ctld; " + "ignoring", port.port_id, name.c_str()); if (!kports.has_port(name)) { if (!kports.add_port(name, port.port_id)) { log_warnx("kports::add_port failed"); @@ -498,8 +498,8 @@ add_nvmf_port(struct conf *conf, const struct cctl_port &port, std::string &name) { if (port.nqn.empty() || port.ctld_transport_group_name.empty()) { - log_debugx("CTL port %u \"%s\" wasn't managed by ctld; ", - port.port_id, name.c_str()); + log_debugx("CTL NVMeoF port %u \"%s\" is not managed by ctld; " + "ignoring", port.port_id, name.c_str()); return; } @@ -549,7 +549,10 @@ conf_new_from_kernel(struct kports &kports) continue; std::string name = port.port_name; - if (port.pp != 0) { + if (port.port_frontend == "ioctl") + name += "/" + std::to_string(port.pp) + "/" + + std::to_string(port.vp); + else if (port.pp != 0 || port.vp != 0) { name += "/" + std::to_string(port.pp); if (port.vp != 0) name += "/" + std::to_string(port.vp); @@ -567,7 +570,7 @@ conf_new_from_kernel(struct kports &kports) for (const auto &lun : devlist.lun_list) { if (lun.ctld_name.empty()) { - log_debugx("CTL lun %ju wasn't managed by ctld; " + log_debugx("CTL lun %ju is not managed by ctld; " "ignoring", (uintmax_t)lun.lun_id); continue; } diff --git a/usr.sbin/spi/spi.c b/usr.sbin/spi/spi.c index 1ced2371e3d0..bbbc3d322b00 100644 --- a/usr.sbin/spi/spi.c +++ b/usr.sbin/spi/spi.c @@ -30,6 +30,7 @@ #include <sys/spigenio.h> #include <sys/sysctl.h> +#include <assert.h> #include <errno.h> #include <fcntl.h> #include <inttypes.h> @@ -364,30 +365,24 @@ main(int argc, char *argv[], char *envp[] __unused) /* do data transfer */ - if (stream) { - while (!err && !feof(stdin)) { - if (fdir == DIR_READ) { - err = perform_read(hdev, &opt); - } - else if (fdir == DIR_WRITE) { - err = perform_write(hdev, &opt); - } - else if (fdir == DIR_READWRITE) { - err = perform_readwrite(hdev, &opt); - } - } - } - else { - if (fdir == DIR_READ) { + assert(fdir != DIR_NONE); + do { + switch (fdir) { + case DIR_READ: err = perform_read(hdev, &opt); - } - else if (fdir == DIR_WRITE) { + break; + case DIR_WRITE: err = perform_write(hdev, &opt); - } - else if (fdir == DIR_READWRITE) { + break; + case DIR_READWRITE: err = perform_readwrite(hdev, &opt); + break; + default: + fprintf(stderr, "Invalid state (%d)\n", fdir); + err = EINVAL; + break; } - } + } while (stream && !err && !feof(stdin)); the_end: diff --git a/usr.sbin/virtual_oss/virtual_oss/virtual_oss.c b/usr.sbin/virtual_oss/virtual_oss/virtual_oss.c index 1d95c87d57b1..42a748a5e3bd 100644 --- a/usr.sbin/virtual_oss/virtual_oss/virtual_oss.c +++ b/usr.sbin/virtual_oss/virtual_oss/virtual_oss.c @@ -783,8 +783,8 @@ virtual_oss_process(void *arg __unused) /* check if compressor should be applied */ voss_compressor(buffer_temp, pvp->rx_compressor_gain, - &pvp->rx_compressor_param, samples, - samples * src_chans, (1ULL << (pvp->bits - 1)) - 1ULL); + &pvp->rx_compressor_param, samples * src_chans, + src_chans, (1ULL << (pvp->bits - 1)) - 1ULL); TAILQ_FOREACH(pvc, &pvp->head, entry) { |
