aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/assert.h61
-rw-r--r--include/rpcsvc/yp_prot.h5
-rw-r--r--lib/libc/gen/fts.39
-rw-r--r--lib/libc/gen/fts.c44
-rw-r--r--lib/libc/tests/gen/fts_options_test.c74
-rw-r--r--lib/libutil/login_class.c4
-rw-r--r--libexec/rc/rc.conf6
-rw-r--r--libexec/rc/rc.d/virtual_oss27
-rw-r--r--sbin/mdmfs/mdmfs.c3
-rw-r--r--sbin/ping/tests/ping_test.sh16
-rw-r--r--sbin/route/route_netlink.c3
-rw-r--r--share/man/man3/assert.376
-rw-r--r--share/man/man4/mac_do.4189
-rw-r--r--stand/defs.mk2
-rw-r--r--stand/efi/Makefile8
-rw-r--r--stand/efi/Makefile.inc5
-rw-r--r--stand/efi/ficl32efi/Makefile3
-rw-r--r--stand/efi/liblua32efi/Makefile3
-rw-r--r--stand/efi/libsa32efi/Makefile1
-rw-r--r--stand/loader.mk4
-rw-r--r--sys/amd64/amd64/machdep.c42
-rw-r--r--sys/amd64/amd64/mem.c103
-rw-r--r--sys/amd64/amd64/support.S7
-rw-r--r--sys/amd64/amd64/uio_machdep.c96
-rw-r--r--sys/amd64/include/md_var.h6
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_sdhci.c1
-rw-r--r--sys/arm64/rockchip/rk_gpio.c106
-rw-r--r--sys/cam/ctl/scsi_ctl.c8
-rw-r--r--sys/compat/linux/linux_mmap.c4
-rw-r--r--sys/compat/linuxkpi/common/src/linux_80211.c24
-rw-r--r--sys/contrib/edk2/Include/Base.h2
-rw-r--r--sys/dev/bnxt/bnxt_en/bnxt_sriov.c39
-rw-r--r--sys/dev/bnxt/bnxt_en/bnxt_sriov.h4
-rw-r--r--sys/dev/bnxt/bnxt_en/if_bnxt.c2
-rw-r--r--sys/dev/cxgbe/adapter.h1
-rw-r--r--sys/dev/cxgbe/common/t4_hw.c1835
-rw-r--r--sys/dev/ffec/if_ffec.c2
-rw-r--r--sys/dev/sound/pcm/sound.c47
-rw-r--r--sys/dev/sound/usb/uaudio.c10
-rw-r--r--sys/dev/uart/uart_dev_ns8250.c44
-rw-r--r--sys/dev/uart/uart_dev_pl011.c30
-rw-r--r--sys/dev/usb/usb_transfer.c2
-rw-r--r--sys/kern/imgact_elf.c129
-rw-r--r--sys/kern/kern_exec.c1
-rw-r--r--sys/kern/syscalls.master2
-rw-r--r--sys/netinet/in_pcb.c23
-rw-r--r--sys/netinet6/in6_pcb.c19
-rw-r--r--sys/netlink/route/iface_drivers.c64
-rw-r--r--sys/netlink/route/rt.c19
-rw-r--r--sys/security/mac_do/mac_do.c1026
-rw-r--r--sys/sys/imgact.h1
-rw-r--r--sys/sys/signal.h4
-rw-r--r--sys/sys/systm.h8
-rw-r--r--sys/x86/x86/ucode.c34
-rw-r--r--tests/sys/acl/run2
-rw-r--r--tests/sys/acl/tools-posix.test14
-rw-r--r--tests/sys/kern/ptrace_test.c8
-rw-r--r--tests/sys/mac/do/Makefile3
-rw-r--r--tests/sys/mac/do/common.sh124
-rw-r--r--tests/sys/mac/do/consistency.sh211
-rw-r--r--tests/sys/mac/do/invalid_configs.sh6
-rw-r--r--tests/sys/mac/do/valid_configs.sh6
-rw-r--r--tests/sys/netipsec/tunnel/Makefile4
-rw-r--r--tools/test/stress2/misc/all.exclude1
-rwxr-xr-xtools/test/stress2/misc/msdos22.sh77
-rwxr-xr-xtools/test/stress2/misc/msdos23.sh77
-rwxr-xr-xtools/test/stress2/misc/msdos24.sh78
-rw-r--r--usr.bin/cap_mkdb/cap_mkdb.c3
-rw-r--r--usr.bin/xinstall/Makefile2
-rw-r--r--usr.bin/xinstall/install.113
-rw-r--r--usr.bin/xinstall/xinstall.c20
-rw-r--r--usr.sbin/bsdinstall/distextract/distextract.c2
-rwxr-xr-xusr.sbin/bsdinstall/scripts/script1
-rw-r--r--usr.sbin/certctl/certctl.c5
-rwxr-xr-xusr.sbin/crashinfo/crashinfo.sh3
-rw-r--r--usr.sbin/ctld/ctld.cc84
-rw-r--r--usr.sbin/ctld/ctld.hh6
-rw-r--r--usr.sbin/ctld/kernel.cc15
-rw-r--r--usr.sbin/spi/spi.c35
-rw-r--r--usr.sbin/virtual_oss/virtual_oss/virtual_oss.c4
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) {