aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.inc14
-rw-r--r--UPDATING5
-rw-r--r--contrib/bsnmp/oid-list18
-rw-r--r--contrib/bsnmp/snmp_mibII/mibII.c6
-rw-r--r--contrib/llvm-project/clang/lib/Sema/AnalysisBasedWarnings.cpp25
-rw-r--r--contrib/smart/Changelog41
-rw-r--r--contrib/smart/LICENSE13
-rw-r--r--contrib/smart/Makefile26
-rw-r--r--contrib/smart/README.md62
-rw-r--r--contrib/smart/freebsd_dev.c821
-rw-r--r--contrib/smart/libsmart.c1359
-rw-r--r--contrib/smart/libsmart.h174
-rw-r--r--contrib/smart/libsmart_desc.c158
-rw-r--r--contrib/smart/libsmart_dev.h60
-rw-r--r--contrib/smart/libsmart_priv.h83
-rw-r--r--contrib/smart/smart.8245
-rw-r--r--contrib/smart/smart.c334
-rw-r--r--etc/mtree/BSD.root.dist2
-rw-r--r--include/unistd.h1
-rw-r--r--lib/geom/part/gpart.84
-rw-r--r--lib/libc/gen/Makefile.inc1
-rw-r--r--lib/libc/gen/Symbol.map1
-rw-r--r--lib/libc/gen/freadlink.c16
-rw-r--r--lib/libc/gen/posix_spawn.c2
-rw-r--r--lib/msun/Makefile6
-rw-r--r--lib/msun/Symbol.map3
-rw-r--r--lib/msun/man/sqrt.353
-rw-r--r--lib/msun/src/math.h3
-rw-r--r--lib/msun/src/math_private.h83
-rw-r--r--lib/msun/src/s_rsqrt.c153
-rw-r--r--lib/msun/src/s_rsqrtf.c155
-rw-r--r--lib/msun/src/s_rsqrtl.c203
-rw-r--r--libexec/nuageinit/nuage.lua43
-rwxr-xr-xlibexec/nuageinit/nuageinit17
-rw-r--r--libexec/nuageinit/tests/Makefile4
-rw-r--r--libexec/nuageinit/tests/adddoas.lua64
-rw-r--r--libexec/nuageinit/tests/addsudo.lua61
-rw-r--r--libexec/nuageinit/tests/decode_base64.lua61
-rw-r--r--libexec/nuageinit/tests/nuage.sh30
-rw-r--r--libexec/nuageinit/tests/nuageinit.sh6
-rw-r--r--libexec/nuageinit/tests/update_sshd_config.lua73
-rw-r--r--packages/Makefile1
-rw-r--r--packages/smart/Makefile4
-rw-r--r--packages/smart/smart.ucl30
-rw-r--r--sbin/fsck_msdosfs/fat.c11
-rw-r--r--sbin/ipfw/ipfw2.c5
-rw-r--r--share/man/man4/rge.44
-rw-r--r--share/man/man4/spkr.4102
-rw-r--r--share/man/man9/Makefile1
-rw-r--r--share/man/man9/uio.945
-rw-r--r--stand/i386/boot2/sio.S2
-rw-r--r--sys/amd64/linux/linux_locore.asm2
-rw-r--r--sys/amd64/linux/linux_support.S2
-rw-r--r--sys/amd64/linux32/linux32_locore.asm2
-rw-r--r--sys/amd64/linux32/linux32_support.S2
-rw-r--r--sys/arm/include/_types.h1
-rw-r--r--sys/arm64/arm64/busdma_bounce.c68
-rw-r--r--sys/arm64/arm64/efirt_machdep.c10
-rw-r--r--sys/arm64/arm64/locore.S2
-rw-r--r--sys/arm64/arm64/machdep.c5
-rw-r--r--sys/arm64/arm64/pmap.c42
-rw-r--r--sys/arm64/arm64/rsi.c185
-rw-r--r--sys/arm64/include/_types.h1
-rw-r--r--sys/arm64/include/pmap.h3
-rw-r--r--sys/arm64/include/rsi.h129
-rw-r--r--sys/arm64/linux/linux_locore.asm2
-rw-r--r--sys/arm64/linux/linux_support.S2
-rw-r--r--sys/compat/linux/linux_vdso_inc.S2
-rw-r--r--sys/compat/linuxkpi/common/src/linux_acpi.c2
-rw-r--r--sys/conf/files.arm642
-rw-r--r--sys/conf/files.riscv9
-rw-r--r--sys/contrib/dev/acpica/changes.txt24
-rw-r--r--sys/contrib/dev/acpica/common/acfileio.c11
-rw-r--r--sys/contrib/dev/acpica/common/acgetline.c2
-rw-r--r--sys/contrib/dev/acpica/common/adfile.c2
-rw-r--r--sys/contrib/dev/acpica/common/adisasm.c2
-rw-r--r--sys/contrib/dev/acpica/common/adwalk.c2
-rw-r--r--sys/contrib/dev/acpica/common/ahids.c10
-rw-r--r--sys/contrib/dev/acpica/common/ahpredef.c2
-rw-r--r--sys/contrib/dev/acpica/common/ahtable.c3
-rw-r--r--sys/contrib/dev/acpica/common/ahuuids.c7
-rw-r--r--sys/contrib/dev/acpica/common/cmfsize.c2
-rw-r--r--sys/contrib/dev/acpica/common/dmextern.c2
-rw-r--r--sys/contrib/dev/acpica/common/dmrestag.c2
-rw-r--r--sys/contrib/dev/acpica/common/dmswitch.c2
-rw-r--r--sys/contrib/dev/acpica/common/dmtable.c7
-rw-r--r--sys/contrib/dev/acpica/common/dmtables.c2
-rw-r--r--sys/contrib/dev/acpica/common/dmtbdump.c2
-rw-r--r--sys/contrib/dev/acpica/common/dmtbdump1.c111
-rw-r--r--sys/contrib/dev/acpica/common/dmtbdump2.c2
-rw-r--r--sys/contrib/dev/acpica/common/dmtbdump3.c2
-rw-r--r--sys/contrib/dev/acpica/common/dmtbinfo.c2
-rw-r--r--sys/contrib/dev/acpica/common/dmtbinfo1.c40
-rw-r--r--sys/contrib/dev/acpica/common/dmtbinfo2.c4
-rw-r--r--sys/contrib/dev/acpica/common/dmtbinfo3.c2
-rw-r--r--sys/contrib/dev/acpica/common/getopt.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslallocate.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslanalyze.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslascii.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslbtypes.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslcache.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslcodegen.c12
-rw-r--r--sys/contrib/dev/acpica/compiler/aslcompile.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslcompiler.h2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslcompiler.l2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslcstyle.y2
-rw-r--r--sys/contrib/dev/acpica/compiler/asldebug.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/asldefine.h2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslerror.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslexternal.c105
-rw-r--r--sys/contrib/dev/acpica/compiler/aslfileio.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslfiles.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslfold.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslglobal.h3
-rw-r--r--sys/contrib/dev/acpica/compiler/aslhelp.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslhelpers.y2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslhex.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslkeywords.y2
-rw-r--r--sys/contrib/dev/acpica/compiler/asllength.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/asllisting.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/asllistsup.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslload.c4
-rw-r--r--sys/contrib/dev/acpica/compiler/asllookup.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslmain.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslmap.c4
-rw-r--r--sys/contrib/dev/acpica/compiler/aslmapenter.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslmapoutput.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslmaputils.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslmessages.c5
-rw-r--r--sys/contrib/dev/acpica/compiler/aslmessages.h3
-rw-r--r--sys/contrib/dev/acpica/compiler/aslmethod.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslnamesp.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/asloffset.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslopcodes.c10
-rw-r--r--sys/contrib/dev/acpica/compiler/asloperands.c32
-rw-r--r--sys/contrib/dev/acpica/compiler/aslopt.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/asloptions.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslparseop.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslparser.y2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslpld.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslpredef.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslprepkg.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslprimaries.y2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslprintf.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslprune.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslresource.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslresources.y2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslrestype1.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslrestype1i.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslrestype2.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslrestype2d.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslrestype2e.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslrestype2q.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslrestype2s.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslrestype2w.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslrules.y2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslstartup.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslstubs.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslsupport.l2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslsupport.y2
-rw-r--r--sys/contrib/dev/acpica/compiler/asltokens.y2
-rw-r--r--sys/contrib/dev/acpica/compiler/asltransform.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/asltree.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/asltypes.h2
-rw-r--r--sys/contrib/dev/acpica/compiler/asltypes.y2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslutils.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/asluuid.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslwalks.c17
-rw-r--r--sys/contrib/dev/acpica/compiler/aslxref.c14
-rw-r--r--sys/contrib/dev/acpica/compiler/aslxrefout.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/cvcompiler.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/cvdisasm.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/cvparser.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/dtcompile.c28
-rw-r--r--sys/contrib/dev/acpica/compiler/dtcompiler.h7
-rw-r--r--sys/contrib/dev/acpica/compiler/dtcompilerparser.l2
-rw-r--r--sys/contrib/dev/acpica/compiler/dtcompilerparser.y2
-rw-r--r--sys/contrib/dev/acpica/compiler/dtexpress.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/dtfield.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/dtio.c8
-rw-r--r--sys/contrib/dev/acpica/compiler/dtparser.l2
-rw-r--r--sys/contrib/dev/acpica/compiler/dtparser.y2
-rw-r--r--sys/contrib/dev/acpica/compiler/dtsubtable.c9
-rw-r--r--sys/contrib/dev/acpica/compiler/dttable.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/dttable1.c133
-rw-r--r--sys/contrib/dev/acpica/compiler/dttable2.c17
-rw-r--r--sys/contrib/dev/acpica/compiler/dttemplate.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/dttemplate.h57
-rw-r--r--sys/contrib/dev/acpica/compiler/dtutils.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/preprocess.h2
-rw-r--r--sys/contrib/dev/acpica/compiler/prexpress.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/prmacros.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/prparser.l2
-rw-r--r--sys/contrib/dev/acpica/compiler/prparser.y2
-rw-r--r--sys/contrib/dev/acpica/compiler/prscan.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/prutils.c2
-rw-r--r--sys/contrib/dev/acpica/components/debugger/dbcmds.c2
-rw-r--r--sys/contrib/dev/acpica/components/debugger/dbconvert.c2
-rw-r--r--sys/contrib/dev/acpica/components/debugger/dbdisply.c2
-rw-r--r--sys/contrib/dev/acpica/components/debugger/dbexec.c2
-rw-r--r--sys/contrib/dev/acpica/components/debugger/dbfileio.c2
-rw-r--r--sys/contrib/dev/acpica/components/debugger/dbhistry.c2
-rw-r--r--sys/contrib/dev/acpica/components/debugger/dbinput.c2
-rw-r--r--sys/contrib/dev/acpica/components/debugger/dbmethod.c2
-rw-r--r--sys/contrib/dev/acpica/components/debugger/dbnames.c2
-rw-r--r--sys/contrib/dev/acpica/components/debugger/dbobject.c2
-rw-r--r--sys/contrib/dev/acpica/components/debugger/dbstats.c2
-rw-r--r--sys/contrib/dev/acpica/components/debugger/dbtest.c2
-rwxr-xr-xsys/contrib/dev/acpica/components/debugger/dbutils.c2
-rw-r--r--sys/contrib/dev/acpica/components/debugger/dbxface.c2
-rw-r--r--sys/contrib/dev/acpica/components/disassembler/dmbuffer.c2
-rw-r--r--sys/contrib/dev/acpica/components/disassembler/dmcstyle.c2
-rw-r--r--sys/contrib/dev/acpica/components/disassembler/dmdeferred.c2
-rw-r--r--sys/contrib/dev/acpica/components/disassembler/dmnames.c2
-rw-r--r--sys/contrib/dev/acpica/components/disassembler/dmopcode.c19
-rw-r--r--sys/contrib/dev/acpica/components/disassembler/dmresrc.c23
-rw-r--r--sys/contrib/dev/acpica/components/disassembler/dmresrcl.c2
-rw-r--r--sys/contrib/dev/acpica/components/disassembler/dmresrcl2.c2
-rw-r--r--sys/contrib/dev/acpica/components/disassembler/dmresrcs.c2
-rw-r--r--sys/contrib/dev/acpica/components/disassembler/dmutils.c2
-rw-r--r--sys/contrib/dev/acpica/components/disassembler/dmwalk.c16
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dsargs.c2
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dscontrol.c2
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dsdebug.c2
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dsfield.c2
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dsinit.c2
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dsmethod.c43
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dsmthdat.c2
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dsobject.c2
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dsopcode.c2
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dspkginit.c2
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dsutils.c2
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dswexec.c2
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dswload.c2
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dswload2.c2
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dswscope.c2
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dswstate.c2
-rw-r--r--sys/contrib/dev/acpica/components/events/evevent.c2
-rw-r--r--sys/contrib/dev/acpica/components/events/evglock.c2
-rw-r--r--sys/contrib/dev/acpica/components/events/evgpe.c2
-rw-r--r--sys/contrib/dev/acpica/components/events/evgpeblk.c2
-rw-r--r--sys/contrib/dev/acpica/components/events/evgpeinit.c2
-rw-r--r--sys/contrib/dev/acpica/components/events/evgpeutil.c2
-rw-r--r--sys/contrib/dev/acpica/components/events/evhandler.c14
-rw-r--r--sys/contrib/dev/acpica/components/events/evmisc.c2
-rw-r--r--sys/contrib/dev/acpica/components/events/evregion.c2
-rw-r--r--sys/contrib/dev/acpica/components/events/evrgnini.c2
-rw-r--r--sys/contrib/dev/acpica/components/events/evsci.c2
-rw-r--r--sys/contrib/dev/acpica/components/events/evxface.c2
-rw-r--r--sys/contrib/dev/acpica/components/events/evxfevnt.c2
-rw-r--r--sys/contrib/dev/acpica/components/events/evxfgpe.c2
-rw-r--r--sys/contrib/dev/acpica/components/events/evxfregn.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exconcat.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exconfig.c29
-rw-r--r--sys/contrib/dev/acpica/components/executer/exconvrt.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/excreate.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exdebug.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exdump.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exfield.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exfldio.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exmisc.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exmutex.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exnames.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exoparg1.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exoparg2.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exoparg3.c12
-rw-r--r--sys/contrib/dev/acpica/components/executer/exoparg6.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exprep.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exregion.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exresnte.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exresolv.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exresop.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exserial.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exstore.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exstoren.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exstorob.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exsystem.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/extrace.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exutils.c2
-rw-r--r--sys/contrib/dev/acpica/components/hardware/hwacpi.c2
-rw-r--r--sys/contrib/dev/acpica/components/hardware/hwesleep.c2
-rw-r--r--sys/contrib/dev/acpica/components/hardware/hwgpe.c2
-rw-r--r--sys/contrib/dev/acpica/components/hardware/hwpci.c2
-rw-r--r--sys/contrib/dev/acpica/components/hardware/hwregs.c2
-rw-r--r--sys/contrib/dev/acpica/components/hardware/hwsleep.c2
-rw-r--r--sys/contrib/dev/acpica/components/hardware/hwtimer.c2
-rw-r--r--sys/contrib/dev/acpica/components/hardware/hwvalid.c2
-rw-r--r--sys/contrib/dev/acpica/components/hardware/hwxface.c2
-rw-r--r--sys/contrib/dev/acpica/components/hardware/hwxfsleep.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsaccess.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsalloc.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsarguments.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsconvert.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsdump.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsdumpdv.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nseval.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsinit.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsload.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsnames.c9
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsobject.c9
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsparse.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nspredef.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsprepkg.c9
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsrepair.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsrepair2.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nssearch.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsutils.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nswalk.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsxfeval.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsxfname.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsxfobj.c2
-rw-r--r--sys/contrib/dev/acpica/components/parser/psargs.c136
-rw-r--r--sys/contrib/dev/acpica/components/parser/psloop.c5
-rw-r--r--sys/contrib/dev/acpica/components/parser/psobject.c2
-rw-r--r--sys/contrib/dev/acpica/components/parser/psopcode.c2
-rw-r--r--sys/contrib/dev/acpica/components/parser/psopinfo.c2
-rw-r--r--sys/contrib/dev/acpica/components/parser/psparse.c2
-rw-r--r--sys/contrib/dev/acpica/components/parser/psscope.c2
-rw-r--r--sys/contrib/dev/acpica/components/parser/pstree.c2
-rw-r--r--sys/contrib/dev/acpica/components/parser/psutils.c2
-rw-r--r--sys/contrib/dev/acpica/components/parser/pswalk.c4
-rw-r--r--sys/contrib/dev/acpica/components/parser/psxface.c2
-rw-r--r--sys/contrib/dev/acpica/components/resources/rsaddr.c2
-rw-r--r--sys/contrib/dev/acpica/components/resources/rscalc.c2
-rw-r--r--sys/contrib/dev/acpica/components/resources/rscreate.c2
-rw-r--r--sys/contrib/dev/acpica/components/resources/rsdump.c2
-rw-r--r--sys/contrib/dev/acpica/components/resources/rsdumpinfo.c2
-rw-r--r--sys/contrib/dev/acpica/components/resources/rsinfo.c2
-rw-r--r--sys/contrib/dev/acpica/components/resources/rsio.c2
-rw-r--r--sys/contrib/dev/acpica/components/resources/rsirq.c2
-rw-r--r--sys/contrib/dev/acpica/components/resources/rslist.c2
-rw-r--r--sys/contrib/dev/acpica/components/resources/rsmemory.c2
-rw-r--r--sys/contrib/dev/acpica/components/resources/rsmisc.c2
-rw-r--r--sys/contrib/dev/acpica/components/resources/rsserial.c9
-rw-r--r--sys/contrib/dev/acpica/components/resources/rsutils.c2
-rw-r--r--sys/contrib/dev/acpica/components/resources/rsxface.c2
-rw-r--r--sys/contrib/dev/acpica/components/tables/tbdata.c2
-rw-r--r--sys/contrib/dev/acpica/components/tables/tbfadt.c5
-rw-r--r--sys/contrib/dev/acpica/components/tables/tbfind.c2
-rw-r--r--sys/contrib/dev/acpica/components/tables/tbinstal.c2
-rw-r--r--sys/contrib/dev/acpica/components/tables/tbprint.c2
-rw-r--r--sys/contrib/dev/acpica/components/tables/tbutils.c2
-rw-r--r--sys/contrib/dev/acpica/components/tables/tbxface.c2
-rw-r--r--sys/contrib/dev/acpica/components/tables/tbxfload.c2
-rw-r--r--sys/contrib/dev/acpica/components/tables/tbxfroot.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utaddress.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utalloc.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utascii.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utbuffer.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utcache.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utcksum.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utcopy.c13
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utdebug.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utdecode.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utdelete.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/uterror.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/uteval.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utexcep.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utglobal.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/uthex.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utids.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utinit.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utlock.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utmath.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utmisc.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utmutex.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utnonansi.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utobject.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utosi.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utownerid.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utpredef.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utresdecode.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utresrc.c34
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utstate.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utstring.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utstrsuppt.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utstrtoul64.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/uttrack.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utuuid.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utxface.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utxferror.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utxfinit.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utxfmutex.c2
-rw-r--r--sys/contrib/dev/acpica/include/acapps.h4
-rw-r--r--sys/contrib/dev/acpica/include/acbuffer.h2
-rw-r--r--sys/contrib/dev/acpica/include/acclib.h2
-rw-r--r--sys/contrib/dev/acpica/include/accommon.h2
-rw-r--r--sys/contrib/dev/acpica/include/acconfig.h2
-rw-r--r--sys/contrib/dev/acpica/include/acconvert.h2
-rw-r--r--sys/contrib/dev/acpica/include/acdebug.h2
-rw-r--r--sys/contrib/dev/acpica/include/acdisasm.h11
-rw-r--r--sys/contrib/dev/acpica/include/acdispat.h2
-rw-r--r--sys/contrib/dev/acpica/include/acevents.h2
-rw-r--r--sys/contrib/dev/acpica/include/acexcep.h2
-rw-r--r--sys/contrib/dev/acpica/include/acglobal.h2
-rw-r--r--sys/contrib/dev/acpica/include/achware.h2
-rw-r--r--sys/contrib/dev/acpica/include/acinterp.h2
-rw-r--r--sys/contrib/dev/acpica/include/aclocal.h3
-rw-r--r--sys/contrib/dev/acpica/include/acmacros.h2
-rw-r--r--sys/contrib/dev/acpica/include/acnames.h2
-rw-r--r--sys/contrib/dev/acpica/include/acnamesp.h2
-rw-r--r--sys/contrib/dev/acpica/include/acobject.h2
-rw-r--r--sys/contrib/dev/acpica/include/acopcode.h2
-rw-r--r--sys/contrib/dev/acpica/include/acoutput.h2
-rw-r--r--sys/contrib/dev/acpica/include/acparser.h2
-rw-r--r--sys/contrib/dev/acpica/include/acpi.h2
-rw-r--r--sys/contrib/dev/acpica/include/acpiosxf.h2
-rw-r--r--sys/contrib/dev/acpica/include/acpixf.h4
-rw-r--r--sys/contrib/dev/acpica/include/acpredef.h6
-rw-r--r--sys/contrib/dev/acpica/include/acresrc.h2
-rw-r--r--sys/contrib/dev/acpica/include/acrestyp.h3
-rw-r--r--sys/contrib/dev/acpica/include/acstruct.h2
-rw-r--r--sys/contrib/dev/acpica/include/actables.h2
-rw-r--r--sys/contrib/dev/acpica/include/actbinfo.h10
-rw-r--r--sys/contrib/dev/acpica/include/actbl.h2
-rw-r--r--sys/contrib/dev/acpica/include/actbl1.h289
-rw-r--r--sys/contrib/dev/acpica/include/actbl2.h2
-rw-r--r--sys/contrib/dev/acpica/include/actbl3.h2
-rw-r--r--sys/contrib/dev/acpica/include/actypes.h2
-rw-r--r--sys/contrib/dev/acpica/include/acutils.h2
-rw-r--r--sys/contrib/dev/acpica/include/acuuid.h7
-rw-r--r--sys/contrib/dev/acpica/include/amlcode.h2
-rw-r--r--sys/contrib/dev/acpica/include/amlresrc.h2
-rw-r--r--sys/contrib/dev/acpica/include/platform/acenv.h2
-rw-r--r--sys/contrib/dev/acpica/include/platform/acenvex.h2
-rw-r--r--sys/contrib/dev/acpica/include/platform/acfreebsd.h2
-rw-r--r--sys/contrib/dev/acpica/include/platform/acgcc.h2
-rw-r--r--sys/contrib/dev/acpica/include/platform/acgccex.h2
-rw-r--r--sys/contrib/dev/acpica/os_specific/service_layers/osgendbg.c2
-rw-r--r--sys/contrib/dev/acpica/os_specific/service_layers/osunixxf.c2
-rw-r--r--sys/dev/acpi_support/acpi_ibm.c2
-rw-r--r--sys/dev/acpica/acpi.c16
-rw-r--r--sys/dev/cxgbe/common/t4_regs.h51
-rw-r--r--sys/dev/cxgbe/firmware/t4fw_interface.h107
-rw-r--r--sys/dev/cxgbe/firmware/t7fw_cfg.txt19
-rw-r--r--sys/dev/cxgbe/firmware/t7fw_cfg_uwire.txt19
-rw-r--r--sys/dev/cxgbe/t4_main.c15
-rw-r--r--sys/dev/eqos/if_eqos_starfive.c12
-rw-r--r--sys/dev/mlx5/mlx5_en/mlx5_en_main.c50
-rw-r--r--sys/dev/pci/pci.c2
-rw-r--r--sys/dev/psci/psci.c11
-rw-r--r--sys/dev/psci/psci.h3
-rw-r--r--sys/dev/rge/if_rge.c1
-rw-r--r--sys/dev/rge/if_rge_vendor.h1
-rw-r--r--sys/dev/syscons/syscons.c4
-rw-r--r--sys/dev/thunderbolt/tbcfg_reg.h2
-rw-r--r--sys/dev/ufshci/ufshci_private.h4
-rw-r--r--sys/dev/vt/vt.h2
-rw-r--r--sys/dev/vt/vt_buf.c30
-rw-r--r--sys/dev/vt/vt_core.c12
-rw-r--r--sys/dev/xen/control/control.c6
-rw-r--r--sys/geom/part/g_part.c1
-rw-r--r--sys/geom/part/g_part.h2
-rw-r--r--sys/geom/part/g_part_gpt.c2
-rw-r--r--sys/i386/linux/linux_locore.asm2
-rw-r--r--sys/kern/subr_physmem.c6
-rw-r--r--sys/kern/subr_power.c16
-rw-r--r--sys/kern/uipc_usrreq.c21
-rw-r--r--sys/kern/vfs_cache.c4
-rw-r--r--sys/kern/vfs_mount.c6
-rw-r--r--sys/kern/vfs_subr.c34
-rw-r--r--sys/kern/vfs_vnops.c4
-rw-r--r--sys/net/ieee8023ad_lacp.c8
-rw-r--r--sys/net/if_geneve.c2
-rw-r--r--sys/net/if_media.h6
-rw-r--r--sys/netpfil/ipfw/ip_fw2.c4
-rw-r--r--sys/powerpc/include/_types.h1
-rw-r--r--sys/riscv/conf/GENERIC1
-rw-r--r--sys/riscv/include/_types.h1
-rw-r--r--sys/riscv/include/bus_dma_impl.h3
-rw-r--r--sys/riscv/include/iommu.h10
-rw-r--r--sys/riscv/iommu/iommu.c1351
-rw-r--r--sys/riscv/iommu/iommu.h359
-rw-r--r--sys/riscv/iommu/iommu_fdt.c145
-rw-r--r--sys/riscv/iommu/iommu_frontend.c505
-rw-r--r--sys/riscv/iommu/iommu_frontend.h38
-rw-r--r--sys/riscv/iommu/iommu_if.m147
-rw-r--r--sys/riscv/iommu/iommu_pci.c172
-rw-r--r--sys/riscv/iommu/iommu_pmap.c629
-rw-r--r--sys/riscv/iommu/iommu_pmap.h49
-rw-r--r--sys/sys/_decls.h46
-rw-r--r--sys/sys/_types.h5
-rw-r--r--sys/sys/abi_types.h2
-rw-r--r--sys/sys/cdefs.h8
-rw-r--r--sys/sys/disk/gpt.h2
-rw-r--r--sys/sys/fcntl.h7
-rw-r--r--sys/sys/malloc.h1
-rw-r--r--sys/sys/mount.h293
-rw-r--r--sys/sys/physmem.h1
-rw-r--r--sys/sys/power.h29
-rw-r--r--sys/sys/time.h4
-rw-r--r--sys/sys/ucred.h11
-rw-r--r--sys/sys/vnode.h30
-rw-r--r--sys/vm/pmap.h1
-rw-r--r--sys/vm/vm_kern.c23
-rw-r--r--sys/vm/vm_map.c3
-rw-r--r--sys/vm/vm_page.c8
-rw-r--r--sys/x86/cpufreq/hwpstate_amd.c2
-rw-r--r--sys/x86/include/_types.h2
-rw-r--r--tests/sys/kern/subr_physmem_test.c33
-rw-r--r--tests/sys/netpfil/common/pft_ping.py13
-rw-r--r--tests/sys/netpfil/ipfw/Makefile1
-rw-r--r--tests/sys/netpfil/ipfw/ipv6-flow-id.sh78
-rw-r--r--tools/build/Makefile1
-rw-r--r--usr.bin/mkimg/gpt.c6
-rw-r--r--usr.bin/mkimg/scheme.c3
-rw-r--r--usr.bin/mkimg/scheme.h3
-rw-r--r--usr.sbin/Makefile1
-rw-r--r--usr.sbin/bsdinstall/bsdinstall.845
-rwxr-xr-xusr.sbin/bsdinstall/scripts/pkgbase.in15
-rwxr-xr-xusr.sbin/bsdinstall/scripts/script71
-rw-r--r--usr.sbin/smart/Makefile8
512 files changed, 10959 insertions, 875 deletions
diff --git a/Makefile.inc1 b/Makefile.inc1
index b07b5f9c1a65..2927054c2e83 100644
--- a/Makefile.inc1
+++ b/Makefile.inc1
@@ -2128,7 +2128,7 @@ real-packages: stage-packages create-packages sign-packages .PHONY
real-update-packages: stage-packages .PHONY
${_+_}${MAKE} -C ${.CURDIR} PKG_VERSION=${PKG_VERSION} create-packages
-.if defined(PKG_VERSION_FROM_DIR)
+.if defined(PKG_VERSION_FROM_DIR) && ${PKG_VERSION} != ${PKG_VERSION_FROM}
@echo "==> Checking for new packages (comparing ${PKG_VERSION} to ${PKG_VERSION_FROM})"
@for pkg in ${PKG_VERSION_FROM_DIR}/${PKG_NAME_PREFIX}-*; do \
pkgname=$$(${PKG_CMD} query -F $${pkg} '%n' | sed 's/${PKG_NAME_PREFIX}-\(.*\)/\1/') ; \
@@ -2146,6 +2146,8 @@ real-update-packages: stage-packages .PHONY
echo "==> New package $${newpkgname}" ; \
fi ; \
done
+.elif defined(PKG_VERSION_FROM_DIR)
+ @echo "==> Package version ${PKG_VERSION} unchanged, keeping old package set"
.else
@echo "==> Bootstrapping repository, not checking for new packages"
.endif
diff --git a/UPDATING b/UPDATING
index c60143c6184e..58d12856c581 100644
--- a/UPDATING
+++ b/UPDATING
@@ -27,6 +27,11 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 16.x IS SLOW:
world, or to merely disable the most expensive debugging functionality
at runtime, run "ln -s 'abort:false,junk:false' /etc/malloc.conf".)
+20260512:
+ "bsdinstall script" will now do a pkgbase installation by default. To
+ revert to the legacy distset installation, set "DISTRIBUTIONS" in
+ your installerconfig.
+
20260412:
The /etc/rc.d/NETWORKING script no longer provides the legacy
NETWORK alias. Third-party or local RC scripts that still use
diff --git a/contrib/bsnmp/oid-list b/contrib/bsnmp/oid-list
index 6bd2fe18c25f..7733cd5be063 100644
--- a/contrib/bsnmp/oid-list
+++ b/contrib/bsnmp/oid-list
@@ -10,11 +10,25 @@ enterprises
12325 FOKUS
1 BEGEMOT
1 BEGEMOT-SNMPD
+ 1 begemotSnmpdObjects
+ 1 begemotSnmpdConfig
+ 2 begemotTrapSinkTable
+ 4 begemotSnmpdPortTable
+ 5 begemotSnmpdCommunityTable
+ 6 begemotSnmpdModuleTable
+ 7 begemotSnmpdStats
+ 8 begemotSnmpdDebug
+ 9 begemotSnmpdLocalPortTable
+ 10 begemotSnmpdTransportMappings
+ 11 begemotSnmpdTransInetTable
+ 13 begemotSnmpdTraps
+ 14 begemotSnmpdContextTable
2 BEGEMOT-NETGRAPH snmpd netgraph module
3 BEGEMOT-IP snmpd IP related stuff.
4 BEGEMOT-IFACE-MIB interface MIB private stuff
5 BEGEMOT-IPSTATS-MIB IP statistics
6 BEGEMOT-IP-MIB IP objects
+ 7 BEGEMOT-VACM VACM support objects
100 BEGEMOT-ILMID snmpd ILMID module
101 BEGEMOT-ATM snmpd ATM module
200 BEGEMOT-PF snmpd PF module (phillip@freebsd.org)
@@ -25,10 +39,14 @@ enterprises
205 begemotBridge bridge module
210 begemotWlan WLAN module
220 begemotHast HAST module
+ 230 begemotJails jails module
300 BEGEMOT-ACM DLR ACM project
303 BEGEMOT-WLINK DLR WLINK simulator
304 BEGEMOT-SATX DLR SatX simulator
+ 305 BEGEMOT-INET inet transport module
+ 306 BEGEMOT-LSOCK local socket transport module
+ 307 BEGEMOT-UDP UDP transport module
405 mysql (vanilla@fatpipi.com)
406 varnish (vanilla@fatpipi.com)
diff --git a/contrib/bsnmp/snmp_mibII/mibII.c b/contrib/bsnmp/snmp_mibII/mibII.c
index 59f3836d1ede..4cf4f231facc 100644
--- a/contrib/bsnmp/snmp_mibII/mibII.c
+++ b/contrib/bsnmp/snmp_mibII/mibII.c
@@ -485,6 +485,7 @@ mib_fetch_ifmib(struct mibif *ifp)
syslog(LOG_WARNING, "sysctl linkmib estimate (%s): %m",
ifp->name);
if (ifp->specmib != NULL) {
+ free(ifp->specmib);
ifp->specmib = NULL;
ifp->specmiblen = 0;
}
@@ -492,6 +493,7 @@ mib_fetch_ifmib(struct mibif *ifp)
}
if (len == 0) {
if (ifp->specmib != NULL) {
+ free(ifp->specmib);
ifp->specmib = NULL;
ifp->specmiblen = 0;
}
@@ -500,6 +502,7 @@ mib_fetch_ifmib(struct mibif *ifp)
if (ifp->specmiblen != len) {
if ((newmib = realloc(ifp->specmib, len)) == NULL) {
+ free(ifp->specmib);
ifp->specmib = NULL;
ifp->specmiblen = 0;
goto out;
@@ -510,6 +513,7 @@ mib_fetch_ifmib(struct mibif *ifp)
if (sysctl(name, nitems(name), ifp->specmib, &len, NULL, 0) == -1) {
syslog(LOG_WARNING, "sysctl linkmib (%s): %m", ifp->name);
if (ifp->specmib != NULL) {
+ free(ifp->specmib);
ifp->specmib = NULL;
ifp->specmiblen = 0;
}
@@ -546,9 +550,11 @@ mib_fetch_ifmib(struct mibif *ifp)
alias_maxlen = MIBIF_ALIAS_SIZE_MAX;
/*
+ * Free any alias memory allocated by a previous call.
* Allocate maximum memory for a buffer and later reallocate
* to free extra memory.
*/
+ free(ifp->alias);
if ((ifp->alias = malloc(alias_maxlen)) == NULL) {
syslog(LOG_WARNING, "malloc(%d) failed: %m", (int)alias_maxlen);
goto fin;
diff --git a/contrib/llvm-project/clang/lib/Sema/AnalysisBasedWarnings.cpp b/contrib/llvm-project/clang/lib/Sema/AnalysisBasedWarnings.cpp
index ec39bca6039f..ab55cbceeaa8 100644
--- a/contrib/llvm-project/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/contrib/llvm-project/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -2116,11 +2116,26 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
void handleNoMutexHeld(const NamedDecl *D, ProtectedOperationKind POK,
AccessKind AK, SourceLocation Loc) override {
- assert((POK == POK_VarAccess || POK == POK_VarDereference) &&
- "Only works for variables");
- unsigned DiagID = POK == POK_VarAccess?
- diag::warn_variable_requires_any_lock:
- diag::warn_var_deref_requires_any_lock;
+ unsigned DiagID = 0;
+ switch (POK) {
+ case POK_VarAccess:
+ case POK_PassByRef:
+ case POK_ReturnByRef:
+ case POK_PassPointer:
+ case POK_ReturnPointer:
+ DiagID = diag::warn_variable_requires_any_lock;
+ break;
+ case POK_VarDereference:
+ case POK_PtPassByRef:
+ case POK_PtReturnByRef:
+ case POK_PtPassPointer:
+ case POK_PtReturnPointer:
+ DiagID = diag::warn_var_deref_requires_any_lock;
+ break;
+ case POK_FunctionCall:
+ llvm_unreachable("Only works for variables");
+ break;
+ }
PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID)
<< D << getLockKindFromAccessKind(AK));
Warnings.emplace_back(std::move(Warning), getNotes());
diff --git a/contrib/smart/Changelog b/contrib/smart/Changelog
new file mode 100644
index 000000000000..ad0e79bade32
--- /dev/null
+++ b/contrib/smart/Changelog
@@ -0,0 +1,41 @@
+This file documents changes for smart releases
+
+version 1.0.3
+ - Fix build errors detected by GCC14
+ - Fix printf build error on 32-bit systems
+
+version 1.0.2
+ - Bring man page up to snuff
+ - Fix various complier warnings
+
+version 1.0.1
+ - Fix don't print attribute ID with description
+
+version 1.0.0
+ - Fix ATA threshold output (gh-10). This is a breaking change as it
+ reduces the output from 4 fields to 3 (drops the "reserved" byte
+ from threshold).
+ - Fix the ATA raw output. This is a breaking change as it increase the
+ output from 6 bytes to 7 (i.e., includes the "reserved" byte). Note
+ that while some attributes use this byte, most do not.
+ - Fix direct debug output (--debug) to standard error
+ - Use POSIX memcpy and memset instead of older bXXX equivalents
+
+version 0.4.2
+ - Update README contents
+
+version 0.4.1
+ - Allow a comma-separated list of attributes
+ - Code refactor + update code comments
+
+version 0.3.0
+
+ - Reclaim the -d option from debug
+ - Change field separator from spaces to tab
+ - Add textual descriptions of attribute IDs for ATA, NVMe, and SCSI
+ - Add a manual page
+ - Fixes
+ * libxo structure for attribute and attributes
+ * simplify LIBXO ifdef sprawl
+ * display of threshold values
+ * display of long values
diff --git a/contrib/smart/LICENSE b/contrib/smart/LICENSE
new file mode 100644
index 000000000000..8b0a0bf6a4a6
--- /dev/null
+++ b/contrib/smart/LICENSE
@@ -0,0 +1,13 @@
+Copyright (c) 2016-2026 Chuck Tuffli <chuck@tuffli.net>
+
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/contrib/smart/Makefile b/contrib/smart/Makefile
new file mode 100644
index 000000000000..64cab720e08f
--- /dev/null
+++ b/contrib/smart/Makefile
@@ -0,0 +1,26 @@
+#
+# Copyright (c) 2016-2021 Chuck Tuffli <chuck@tuffli.net>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+PROG= smart
+SRCS= smart.c libsmart.c libsmart_desc.c
+SRCS+= freebsd_dev.c
+LIBADD= cam xo
+MAN=smart.8
+MLINKS= smart.8 diskhealth.8
+#CFLAGS+= -ggdb -O0
+CFLAGS+= -DLIBXO
+LINKS= ${BINDIR}/smart ${BINDIR}/diskhealth
+
+.include <bsd.prog.mk>
diff --git a/contrib/smart/README.md b/contrib/smart/README.md
new file mode 100644
index 000000000000..57fc685a9ef8
--- /dev/null
+++ b/contrib/smart/README.md
@@ -0,0 +1,62 @@
+# README #
+
+### What is this repository for? ###
+
+* Application to output the SMART values of disks
+
+### How do I get set up? ###
+
+Clone this repository onto a FreeBSD box and run make
+
+ $ git clone https://github.com/ctuffli/smart
+ $ cd smart && make
+
+or install it from ports ( http://www.freshports.org/sysutils/smart/ )
+
+### How to use
+ Usage: smart [-htxi] [-a attribute[,attribute]...] <device name>
+ -h, --help
+ -t, --threshold : also print out the threshold values
+ -x, --hex : print the values out in hexadecimal
+ -a, --attribute : print a specific attribute(s)
+ -i, --info : print general device information
+ -d, --decode: decode the attribute IDs
+ -D, --no-decode: don't decode the attribute IDs
+ -v, --version : print the version and copyright
+
+### Example
+* List the raw attributes of SATA device /dev/ada0
+
+ smart ada0
+
+* List the decoded attributes of NVMe device /dev/nda0
+
+ smart -d nda0
+
+ or
+
+ diskhealth nda0
+
+### What does the raw output mean?
+The format and location of SMART / health data varies across protocols.
+To simplify the output, the application uses a Dumb Unified Model of
+SMART Buffers. In this model, SMART data is located in one or more log
+pages. Each page contains one or more values ("attributes")
+differentiated by an ID. Note that ID's are only unique within a log
+page. Thus, the application outputs:
+
+ <Log Page ID> <Attribute ID> <Attribute value>
+for each selected attribute. Threshold values, if defined by the protocol
+and selected by the user, are printed after the attribute value.
+
+See the shell scripts `atasmart`, `nvmesmart`, and `scsismart` for examples of parsing the output.
+
+### What is the decoded output?
+Decoded output converts numeric values (Log Page, Attribute ID and Value tuples) into human-readable descriptions.
+
+The output for protocols like NVMe and SCSI which provide standardized descriptions will match the text in the specification. ATA, however, allows vendors to define their own attributes. For ATA, descriptions come from the "SMART Attribute Descriptions (SAD)" (ANSI - INCITS TR-54) specification which documents attributes common to multiple ATA drive vendors.
+
+### Protocol Specific Notes
+* __ATA__ : The attribute and values follow the 'standard'. The log page is the Feature value used in ATA command. Thus, the default page is 208 / 0xd0 (a.k.a SMART Read Data). The threshold values printed are status flags, current value, and worst value. The SMART Return Status (Feature 218 / 0xda) indicates the reliability status of the device and is sometimes used as a top-level SMART health indication. While this command does not return data, the application encodes "no errors" as 0x0 and "threshold exceeded" as 0x1 in attribute 0.
+* __NVMe__ : The Log Page is the SMART / Health Information LID value in the Get Log Page command (i.e. 0x2). The attribute ID is the byte offset within this page.
+* __SCSI__ : The Log Page ID is the Page Code value in the Mode Sense command. The attribute ID is the parameter code defined by this page (e.g. 0 in the Write Error Counters log page is 'Errors corrected without substantial delay'). The values will depend on the Page Codes supported by a drive.
diff --git a/contrib/smart/freebsd_dev.c b/contrib/smart/freebsd_dev.c
new file mode 100644
index 000000000000..ee861fdec577
--- /dev/null
+++ b/contrib/smart/freebsd_dev.c
@@ -0,0 +1,821 @@
+/*
+ * Copyright (c) 2016-2021 Chuck Tuffli <chuck@tuffli.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <err.h>
+#include <errno.h>
+#include <camlib.h>
+#include <cam/scsi/scsi_message.h>
+
+#include "libsmart.h"
+#include "libsmart_priv.h"
+#include "libsmart_dev.h"
+
+/* Provide compatibility for FreeBSD 11.0 */
+#if (__FreeBSD_version < 1101000)
+
+struct scsi_log_informational_exceptions {
+ struct scsi_log_param_header hdr;
+#define SLP_IE_GEN 0x0000
+ uint8_t ie_asc;
+ uint8_t ie_ascq;
+ uint8_t temperature;
+};
+
+#endif
+
+struct fbsd_smart {
+ smart_t common;
+ struct cam_device *camdev;
+};
+
+static smart_protocol_e __device_get_proto(struct fbsd_smart *);
+static bool __device_proto_tunneled(struct fbsd_smart *);
+static int32_t __device_get_info(struct fbsd_smart *);
+
+smart_h
+device_open(smart_protocol_e protocol, char *devname)
+{
+ struct fbsd_smart *h = NULL;
+
+ h = malloc(sizeof(struct fbsd_smart));
+ if (h == NULL)
+ return NULL;
+
+ memset(h, 0, sizeof(struct fbsd_smart));
+
+ h->common.protocol = SMART_PROTO_MAX;
+ h->camdev = cam_open_device(devname, O_RDWR);
+ if (h->camdev == NULL) {
+ printf("%s: error opening %s - %s\n",
+ __func__, devname,
+ cam_errbuf);
+ free(h);
+ h = NULL;
+ } else {
+ smart_protocol_e proto = __device_get_proto(h);
+
+ if ((protocol == SMART_PROTO_AUTO) ||
+ (protocol == proto)) {
+ h->common.protocol = proto;
+ } else {
+ printf("%s: protocol mismatch %d vs %d\n",
+ __func__, protocol, proto);
+ }
+
+ if (proto == SMART_PROTO_SCSI) {
+ if (__device_proto_tunneled(h)) {
+ h->common.protocol = SMART_PROTO_ATA;
+ h->common.info.tunneled = 1;
+ }
+ }
+
+ __device_get_info(h);
+ }
+
+ return h;
+}
+
+void
+device_close(smart_h h)
+{
+ struct fbsd_smart *fsmart = h;
+
+ if (fsmart != NULL) {
+ if (fsmart->camdev != NULL) {
+ cam_close_device(fsmart->camdev);
+ }
+
+ free(fsmart);
+ }
+}
+
+static const uint8_t smart_read_data[] = {
+ 0xb0, 0xd0, 0x00, 0x4f, 0xc2, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const uint8_t smart_return_status[] = {
+ 0xb0, 0xda, 0x00, 0x4f, 0xc2, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static int32_t
+__device_read_ata(smart_h h, uint32_t page, void *buf, size_t bsize, union ccb *ccb)
+{
+ struct fbsd_smart *fsmart = h;
+ const uint8_t *smart_fis;
+ uint32_t smart_fis_size = 0;
+ uint32_t flags = 0;
+ uint16_t sector_count = 0;
+ uint8_t protocol = 0;
+
+ switch (page) {
+ case PAGE_ID_ATA_SMART_READ_DATA: /* Support SMART READ DATA */
+ smart_fis = smart_read_data;
+ smart_fis_size = sizeof(smart_read_data);
+ flags = CAM_DIR_IN;
+ sector_count = 1;
+ protocol = AP_PROTO_PIO_IN;
+ break;
+ case PAGE_ID_ATA_SMART_RET_STATUS: /* Support SMART RETURN STATUS */
+ smart_fis = smart_return_status;
+ smart_fis_size = sizeof(smart_return_status);
+ /* Command has no data but uses the return status */
+ flags = CAM_DIR_NONE;
+ protocol = AP_PROTO_NON_DATA;
+ bsize = 0;
+ break;
+ default:
+ return EINVAL;
+ }
+
+ if (fsmart->common.info.tunneled) {
+ struct ata_pass_16 *cdb;
+ uint8_t cdb_flags;
+
+ if (bsize > 0) {
+ cdb_flags = AP_FLAG_TDIR_FROM_DEV |
+ AP_FLAG_BYT_BLOK_BLOCKS |
+ AP_FLAG_TLEN_SECT_CNT;
+ } else {
+ cdb_flags = AP_FLAG_CHK_COND |
+ AP_FLAG_TDIR_FROM_DEV |
+ AP_FLAG_BYT_BLOK_BLOCKS;
+ }
+
+ cdb = (struct ata_pass_16 *)ccb->csio.cdb_io.cdb_bytes;
+ memset(cdb, 0, sizeof(*cdb));
+
+ scsi_ata_pass_16(&ccb->csio,
+ /*retries*/ 1,
+ /*cbfcnp*/ NULL,
+ /*flags*/ flags,
+ /*tag_action*/ MSG_SIMPLE_Q_TAG,
+ /*protocol*/ protocol,
+ /*ata_flags*/ cdb_flags,
+ /*features*/ page,
+ /*sector_count*/sector_count,
+ /*lba*/ 0,
+ /*command*/ ATA_SMART_CMD,
+ /*control*/ 0,
+ /*data_ptr*/ buf,
+ /*dxfer_len*/ bsize,
+ /*sense_len*/ SSD_FULL_SIZE,
+ /*timeout*/ 5000
+ );
+ cdb->lba_mid = 0x4f;
+ cdb->lba_high = 0xc2;
+ cdb->device = 0; /* scsi_ata_pass_16() sets this */
+ } else {
+ memcpy(&ccb->ataio.cmd.command, smart_fis, smart_fis_size);
+
+ cam_fill_ataio(&ccb->ataio,
+ /* retries */1,
+ /* cbfcnp */NULL,
+ /* flags */flags,
+ /* tag_action */0,
+ /* data_ptr */buf,
+ /* dxfer_len */bsize,
+ /* timeout */5000);
+ ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
+ ccb->ataio.cmd.control = 0;
+ }
+
+ return 0;
+}
+
+static int32_t
+__device_read_scsi(__attribute__((unused)) smart_h h, uint32_t page, void *buf, size_t bsize, union ccb *ccb)
+{
+
+ scsi_log_sense(&ccb->csio,
+ /* retries */1,
+ /* cbfcnp */NULL,
+ /* tag_action */0,
+ /* page_code */SLS_PAGE_CTRL_CUMULATIVE,
+ /* page */page,
+ /* save_pages */0,
+ /* ppc */0,
+ /* paramptr */0,
+ /* param_buf */buf,
+ /* param_len */bsize,
+ /* sense_len */0,
+ /* timeout */5000);
+
+ return 0;
+}
+
+static int32_t
+__device_read_nvme(__attribute__((unused)) smart_h h, uint32_t page, void *buf, size_t bsize, union ccb *ccb)
+{
+ struct ccb_nvmeio *nvmeio = &ccb->nvmeio;
+ uint32_t numd = 0; /* number of dwords */
+
+ /*
+ * NVME CAM passthru
+ * 1200000 > version > 1101510 uses nvmeio->cmd.opc
+ * 1200059 > version > 1200038 uses nvmeio->cmd.opc
+ * 1200081 > version > 1200058 uses nvmeio->cmd.opc_fuse
+ * > 1200080 uses nvmeio->cmd.opc
+ * This code doesn't support the brief 'opc_fuse' period.
+ */
+#if ((__FreeBSD_version > 1200038) || ((__FreeBSD_version > 1101510) && (__FreeBSD_version < 1200000)))
+ switch (page) {
+ case NVME_LOG_HEALTH_INFORMATION:
+ numd = (sizeof(struct nvme_health_information_page) / sizeof(uint32_t));
+ break;
+ default:
+ /* Unsupported log page */
+ return EINVAL;
+ }
+
+ /* Subtract 1 because NUMD is a zero based value */
+ numd--;
+
+ nvmeio->cmd.opc = NVME_OPC_GET_LOG_PAGE;
+ nvmeio->cmd.nsid = NVME_GLOBAL_NAMESPACE_TAG;
+ nvmeio->cmd.cdw10 = page | (numd << 16);
+
+ cam_fill_nvmeadmin(&ccb->nvmeio,
+ /* retries */1,
+ /* cbfcnp */NULL,
+ /* flags */CAM_DIR_IN,
+ /* data_ptr */buf,
+ /* dxfer_len */bsize,
+ /* timeout */5000);
+#endif
+ return 0;
+}
+
+/*
+ * Retrieve the SMART RETURN STATUS
+ *
+ * SMART RETURN STATUS provides the reliability status of the
+ * device and can be used as a high-level indication of health.
+ */
+static int32_t
+__device_status_ata(smart_h h, union ccb *ccb)
+{
+ struct fbsd_smart *fsmart = h;
+ uint8_t *buf = NULL;
+ uint32_t page = 0;
+ uint8_t lba_high = 0, lba_mid = 0, device = 0, status = 0;
+
+ if (fsmart->common.info.tunneled) {
+ struct ata_res_pass16 {
+ u_int16_t reserved[5];
+ u_int8_t flags;
+ u_int8_t error;
+ u_int8_t sector_count_exp;
+ u_int8_t sector_count;
+ u_int8_t lba_low_exp;
+ u_int8_t lba_low;
+ u_int8_t lba_mid_exp;
+ u_int8_t lba_mid;
+ u_int8_t lba_high_exp;
+ u_int8_t lba_high;
+ u_int8_t device;
+ u_int8_t status;
+ } *res_pass16 = (struct ata_res_pass16 *)(uintptr_t)
+ &ccb->csio.sense_data;
+
+ buf = ccb->csio.data_ptr;
+ page = ((struct ata_pass_16 *)ccb->csio.cdb_io.cdb_bytes)->features;
+ lba_high = res_pass16->lba_high;
+ lba_mid = res_pass16->lba_mid;
+ device = res_pass16->device;
+ status = res_pass16->status;
+
+ /*
+ * Note that this generates an expected CHECK CONDITION.
+ * Mask it so the outer function doesn't print an error
+ * message.
+ */
+ ccb->ccb_h.status &= ~CAM_STATUS_MASK;
+ ccb->ccb_h.status |= CAM_REQ_CMP;
+ } else {
+ struct ccb_ataio *ataio = (struct ccb_ataio *)&ccb->ataio;
+
+ buf = ataio->data_ptr;
+ page = ataio->cmd.features;
+ lba_high = ataio->res.lba_high;
+ lba_mid = ataio->res.lba_mid;
+ device = ataio->res.device;
+ status = ataio->res.status;
+ }
+
+ switch (page) {
+ case PAGE_ID_ATA_SMART_RET_STATUS:
+ /*
+ * Typically, SMART related log pages return data, but this
+ * command is different in that the data is encoded in the
+ * result registers.
+ *
+ * Handle this in a UNIX-like way by writing a 0 (no errors)
+ * or 1 (threshold exceeded condition) to the output buffer.
+ */
+ dprintf("SMART_RET_STATUS: lba mid=%#x high=%#x device=%#x status=%#x\n",
+ lba_mid,
+ lba_high,
+ device,
+ status);
+ if ((lba_high == 0x2c) && (lba_mid == 0xf4)) {
+ buf[0] = 1;
+ } else if ((lba_high == 0xc2) && (lba_mid == 0x4f)) {
+ buf[0] = 0;
+ } else {
+ /* Ruh-roh ... */
+ buf[0] = 255;
+ }
+ break;
+ default:
+ ;
+ }
+
+ return 0;
+}
+
+int32_t
+device_read_log(smart_h h, uint32_t page, void *buf, size_t bsize)
+{
+ struct fbsd_smart *fsmart = h;
+ union ccb *ccb = NULL;
+ int rc = 0;
+
+ if (fsmart == NULL)
+ return EINVAL;
+
+ dprintf("read log page %#x\n", page);
+
+ ccb = cam_getccb(fsmart->camdev);
+ if (ccb == NULL)
+ return ENOMEM;
+
+ CCB_CLEAR_ALL_EXCEPT_HDR(ccb);
+
+ switch (fsmart->common.protocol) {
+ case SMART_PROTO_ATA:
+ rc = __device_read_ata(h, page, buf, bsize, ccb);
+ break;
+ case SMART_PROTO_SCSI:
+ rc = __device_read_scsi(h, page, buf, bsize, ccb);
+ break;
+ case SMART_PROTO_NVME:
+ rc = __device_read_nvme(h, page, buf, bsize, ccb);
+ break;
+ default:
+ warnx("unsupported protocol %d", fsmart->common.protocol);
+ cam_freeccb(ccb);
+ return ENODEV;
+ }
+
+ if (rc) {
+ if (rc == EINVAL)
+ warnx("unsupported page %#x", page);
+
+ return rc;
+ }
+
+ if (((rc = cam_send_ccb(fsmart->camdev, ccb)) < 0)
+ || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
+ if (rc < 0)
+ warn("error sending command");
+ }
+
+ /*
+ * Most commands don't need any post-processing. But then there's
+ * ATA. It's why we can't have nice things :(
+ */
+ switch (fsmart->common.protocol) {
+ case SMART_PROTO_ATA:
+ __device_status_ata(h, ccb);
+ break;
+ default:
+ ;
+ }
+
+ if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+ cam_error_print(fsmart->camdev, ccb, CAM_ESF_ALL,
+ CAM_EPF_ALL, stderr);
+ }
+
+ cam_freeccb(ccb);
+
+ return 0;
+}
+
+/*
+ * The SCSI / ATA Translation (SAT) requires devices to support the ATA
+ * Information VPD Page (T10/2126-D Revision 04). Use the existence of
+ * this page to identify tunneled devices.
+ */
+static bool
+__device_proto_tunneled(struct fbsd_smart *fsmart)
+{
+ union ccb *ccb = NULL;
+ struct scsi_vpd_supported_page_list supportedp;
+ uint32_t i;
+ bool is_tunneled = false;
+
+ if (fsmart->common.protocol != SMART_PROTO_SCSI) {
+ return false;
+ }
+
+ ccb = cam_getccb(fsmart->camdev);
+ if (!ccb) {
+ warn("Allocation failure ccb=%p", ccb);
+ goto __device_proto_tunneled_out;
+ }
+
+ scsi_inquiry(&ccb->csio,
+ 3, // retries
+ NULL, // callback function
+ MSG_SIMPLE_Q_TAG, // tag action
+ (uint8_t *)&supportedp,
+ sizeof(struct scsi_vpd_supported_page_list),
+ 1, // EVPD
+ SVPD_SUPPORTED_PAGE_LIST, // page code
+ SSD_FULL_SIZE, // sense length
+ 5000); // timeout
+
+ ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
+
+ if ((cam_send_ccb(fsmart->camdev, ccb) >= 0) &&
+ ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)) {
+ dprintf("Looking for page %#x (total = %u):\n", SVPD_ATA_INFORMATION,
+ supportedp.length);
+ for (i = 0; i < supportedp.length; i++) {
+ dprintf("\t[%u] = %#x\n", i, supportedp.list[i]);
+ if (supportedp.list[i] == SVPD_ATA_INFORMATION) {
+ is_tunneled = true;
+ break;
+ }
+ }
+ }
+
+ cam_freeccb(ccb);
+
+__device_proto_tunneled_out:
+ return is_tunneled;
+}
+
+/**
+ * Retrieve the device protocol type via the transport settings
+ *
+ * @return protocol type or SMART_PROTO_MAX on error
+ */
+static smart_protocol_e
+__device_get_proto(struct fbsd_smart *fsmart)
+{
+ smart_protocol_e proto = SMART_PROTO_MAX;
+ union ccb *ccb;
+
+ if (!fsmart || !fsmart->camdev) {
+ warn("Bad handle %p", fsmart);
+ return proto;
+ }
+
+ ccb = cam_getccb(fsmart->camdev);
+ if (ccb != NULL) {
+ CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cts);
+
+ ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
+ ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
+
+ if (cam_send_ccb(fsmart->camdev, ccb) >= 0) {
+ if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
+ struct ccb_trans_settings *cts = &ccb->cts;
+
+ switch (cts->protocol) {
+ case PROTO_ATA:
+ proto = SMART_PROTO_ATA;
+ break;
+ case PROTO_SCSI:
+ proto = SMART_PROTO_SCSI;
+ break;
+ case PROTO_NVME:
+ proto = SMART_PROTO_NVME;
+ break;
+ default:
+ printf("%s: unknown protocol %d\n",
+ __func__,
+ cts->protocol);
+ }
+ }
+ }
+
+ cam_freeccb(ccb);
+ }
+
+ return proto;
+}
+
+static int32_t
+__device_info_ata(struct fbsd_smart *fsmart, struct ccb_getdev *cgd)
+{
+ smart_info_t *sinfo = NULL;
+
+ if (!fsmart || !cgd) {
+ return -1;
+ }
+
+ sinfo = &fsmart->common.info;
+
+ sinfo->supported = cgd->ident_data.support.command1 &
+ ATA_SUPPORT_SMART;
+
+ dprintf("ATA command1 = %#x\n", cgd->ident_data.support.command1);
+
+ cam_strvis((uint8_t *)sinfo->device, cgd->ident_data.model,
+ sizeof(cgd->ident_data.model),
+ sizeof(sinfo->device));
+ cam_strvis((uint8_t *)sinfo->rev, cgd->ident_data.revision,
+ sizeof(cgd->ident_data.revision),
+ sizeof(sinfo->rev));
+ cam_strvis((uint8_t *)sinfo->serial, cgd->ident_data.serial,
+ sizeof(cgd->ident_data.serial),
+ sizeof(sinfo->serial));
+
+ return 0;
+}
+
+static int32_t
+__device_info_scsi(struct fbsd_smart *fsmart, struct ccb_getdev *cgd)
+{
+ smart_info_t *sinfo = NULL;
+ union ccb *ccb = NULL;
+ struct scsi_vpd_unit_serial_number *snum = NULL;
+ struct scsi_log_informational_exceptions ie = {0};
+
+ if (!fsmart || !cgd) {
+ return -1;
+ }
+
+ sinfo = &fsmart->common.info;
+
+ cam_strvis((uint8_t *)sinfo->vendor, (uint8_t *)cgd->inq_data.vendor,
+ sizeof(cgd->inq_data.vendor),
+ sizeof(sinfo->vendor));
+ cam_strvis((uint8_t *)sinfo->device, (uint8_t *)cgd->inq_data.product,
+ sizeof(cgd->inq_data.product),
+ sizeof(sinfo->device));
+ cam_strvis((uint8_t *)sinfo->rev, (uint8_t *)cgd->inq_data.revision,
+ sizeof(cgd->inq_data.revision),
+ sizeof(sinfo->rev));
+
+ ccb = cam_getccb(fsmart->camdev);
+ snum = malloc(sizeof(struct scsi_vpd_unit_serial_number));
+ if (!ccb || !snum) {
+ warn("Allocation failure ccb=%p snum=%p", ccb, snum);
+ goto __device_info_scsi_out;
+ }
+
+ /* Get the serial number */
+ CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
+
+ scsi_inquiry(&ccb->csio,
+ 3, // retries
+ NULL, // callback function
+ MSG_SIMPLE_Q_TAG, // tag action
+ (uint8_t *)snum,
+ sizeof(struct scsi_vpd_unit_serial_number),
+ 1, // EVPD
+ SVPD_UNIT_SERIAL_NUMBER, // page code
+ SSD_FULL_SIZE, // sense length
+ 5000); // timeout
+
+ ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
+
+ if ((cam_send_ccb(fsmart->camdev, ccb) >= 0) &&
+ ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)) {
+ cam_strvis((uint8_t *)sinfo->serial, snum->serial_num,
+ snum->length,
+ sizeof(sinfo->serial));
+ sinfo->serial[sizeof(sinfo->serial) - 1] = '\0';
+ }
+
+ memset(ccb, 0, sizeof(*ccb));
+
+ scsi_log_sense(&ccb->csio,
+ /* retries */1,
+ /* cbfcnp */NULL,
+ /* tag_action */0,
+ /* page_code */SLS_PAGE_CTRL_CUMULATIVE,
+ /* page */SLS_IE_PAGE,
+ /* save_pages */0,
+ /* ppc */0,
+ /* paramptr */0,
+ /* param_buf */(uint8_t *)&ie,
+ /* param_len */sizeof(ie),
+ /* sense_len */0,
+ /* timeout */5000);
+
+ /*
+ * Note: The existance of the Informational Exceptions (IE) log page
+ * appears to be the litmus test for SMART support in SCSI
+ * devices. Confusingly, smartctl will report SMART health
+ * status as 'OK' if the device doesn't support the IE page.
+ * For now, just report the facts.
+ */
+ if ((cam_send_ccb(fsmart->camdev, ccb) >= 0) &&
+ ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)) {
+ if ((ie.hdr.param_len < 4) || ie.ie_asc || ie.ie_ascq) {
+ printf("Log Sense, Informational Exceptions failed "
+ "(length=%u asc=%#x ascq=%#x)\n",
+ ie.hdr.param_len, ie.ie_asc, ie.ie_ascq);
+ } else {
+ sinfo->supported = true;
+ }
+ }
+
+__device_info_scsi_out:
+ free(snum);
+ if (ccb)
+ cam_freeccb(ccb);
+
+ return 0;
+}
+
+static int32_t
+__device_info_nvme(struct fbsd_smart *fsmart, struct ccb_getdev *cgd)
+{
+ union ccb *ccb;
+ smart_info_t *sinfo = NULL;
+ struct nvme_controller_data cd;
+
+ if (!fsmart || !cgd) {
+ return -1;
+ }
+
+ sinfo = &fsmart->common.info;
+
+ sinfo->supported = true;
+
+ ccb = cam_getccb(fsmart->camdev);
+ if (ccb != NULL) {
+ struct ccb_dev_advinfo *cdai = &ccb->cdai;
+
+ CCB_CLEAR_ALL_EXCEPT_HDR(cdai);
+
+ cdai->ccb_h.func_code = XPT_DEV_ADVINFO;
+ cdai->ccb_h.flags = CAM_DIR_IN;
+ cdai->flags = CDAI_FLAG_NONE;
+#ifdef CDAI_TYPE_NVME_CNTRL
+ cdai->buftype = CDAI_TYPE_NVME_CNTRL;
+#else
+ cdai->buftype = 6;
+#endif
+ cdai->bufsiz = sizeof(struct nvme_controller_data);
+ cdai->buf = (uint8_t *)&cd;
+
+ if (cam_send_ccb(fsmart->camdev, ccb) >= 0) {
+ if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
+ cam_strvis((uint8_t *)sinfo->device, cd.mn,
+ sizeof(cd.mn),
+ sizeof(sinfo->device));
+ cam_strvis((uint8_t *)sinfo->rev, cd.fr,
+ sizeof(cd.fr),
+ sizeof(sinfo->rev));
+ cam_strvis((uint8_t *)sinfo->serial, cd.sn,
+ sizeof(cd.sn),
+ sizeof(sinfo->serial));
+ }
+ }
+
+ cam_freeccb(ccb);
+ }
+
+ return 0;
+}
+
+static int32_t
+__device_info_tunneled_ata(struct fbsd_smart *fsmart)
+{
+ struct ata_params ident_data;
+ union ccb *ccb = NULL;
+ int32_t rc = -1;
+
+ ccb = cam_getccb(fsmart->camdev);
+ if (ccb == NULL) {
+ goto __device_info_tunneled_ata_out;
+ }
+
+ memset(&ident_data, 0, sizeof(struct ata_params));
+
+ CCB_CLEAR_ALL_EXCEPT_HDR(ccb);
+
+ scsi_ata_pass_16(&ccb->csio,
+ /*retries*/ 1,
+ /*cbfcnp*/ NULL,
+ /*flags*/ CAM_DIR_IN,
+ /*tag_action*/ MSG_SIMPLE_Q_TAG,
+ /*protocol*/ AP_PROTO_PIO_IN,
+ /*ata_flags*/ AP_FLAG_TLEN_SECT_CNT |
+ AP_FLAG_BYT_BLOK_BLOCKS |
+ AP_FLAG_TDIR_FROM_DEV,
+ /*features*/ 0,
+ /*sector_count*/sizeof(struct ata_params),
+ /*lba*/ 0,
+ /*command*/ ATA_ATA_IDENTIFY,
+ /*control*/ 0,
+ /*data_ptr*/ (uint8_t *)&ident_data,
+ /*dxfer_len*/ sizeof(struct ata_params),
+ /*sense_len*/ SSD_FULL_SIZE,
+ /*timeout*/ 5000
+ );
+
+ rc = cam_send_ccb(fsmart->camdev, ccb);
+ if (rc != 0) {
+ warnx("%s: scsi_ata_pass_16() failed (programmer error?)",
+ __func__);
+ goto __device_info_tunneled_ata_out;
+ }
+
+ fsmart->common.info.supported = ident_data.support.command1 &
+ ATA_SUPPORT_SMART;
+
+ dprintf("ATA command1 = %#x\n", ident_data.support.command1);
+
+__device_info_tunneled_ata_out:
+ if (ccb) {
+ cam_freeccb(ccb);
+ }
+
+ return rc;
+}
+
+/**
+ * Retrieve the device information and use to populate the info structure
+ */
+static int32_t
+__device_get_info(struct fbsd_smart *fsmart)
+{
+ union ccb *ccb;
+ int32_t rc = -1;
+
+ if (!fsmart || !fsmart->camdev) {
+ warn("Bad handle %p", fsmart);
+ return -1;
+ }
+
+ ccb = cam_getccb(fsmart->camdev);
+ if (ccb != NULL) {
+ struct ccb_getdev *cgd = &ccb->cgd;
+
+ CCB_CLEAR_ALL_EXCEPT_HDR(cgd);
+
+ /*
+ * GDEV_TYPE doesn't support NVMe. What we do get is:
+ * - device (ata/model, scsi/product)
+ * - revision (ata, scsi)
+ * - serial (ata)
+ * - vendor (scsi)
+ * - supported (ata)
+ *
+ * Serial # for all proto via ccb_dev_advinfo (buftype CDAI_TYPE_SERIAL_NUM)
+ */
+ ccb->ccb_h.func_code = XPT_GDEV_TYPE;
+
+ if (cam_send_ccb(fsmart->camdev, ccb) >= 0) {
+ if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
+ switch (cgd->protocol) {
+ case PROTO_ATA:
+ rc = __device_info_ata(fsmart, cgd);
+ break;
+ case PROTO_SCSI:
+ rc = __device_info_scsi(fsmart, cgd);
+ if (!rc && fsmart->common.protocol == SMART_PROTO_ATA) {
+ rc = __device_info_tunneled_ata(fsmart);
+ }
+ break;
+ case PROTO_NVME:
+ rc = __device_info_nvme(fsmart, cgd);
+ break;
+ default:
+ printf("%s: unsupported protocol %d\n",
+ __func__, cgd->protocol);
+ }
+ }
+ }
+
+ cam_freeccb(ccb);
+ }
+
+ return rc;
+}
diff --git a/contrib/smart/libsmart.c b/contrib/smart/libsmart.c
new file mode 100644
index 000000000000..012615bacdbd
--- /dev/null
+++ b/contrib/smart/libsmart.c
@@ -0,0 +1,1359 @@
+/*
+ * Copyright (c) 2016-2026 Chuck Tuffli <chuck@tuffli.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <assert.h>
+#include <err.h>
+#include <string.h>
+#include <sys/endian.h>
+
+#ifdef LIBXO
+#include <libxo/xo.h>
+#endif
+
+#include "libsmart.h"
+#include "libsmart_priv.h"
+#include "libsmart_dev.h"
+
+/* Default page lists */
+
+static smart_page_list_t pg_list_ata = {
+ .pg_count = 2,
+ .pages = {
+ { .id = PAGE_ID_ATA_SMART_READ_DATA, .bytes = 512 },
+ { .id = PAGE_ID_ATA_SMART_RET_STATUS, .bytes = 4 }
+ }
+};
+
+#define PAGE_ID_NVME_SMART_HEALTH 0x02
+
+static smart_page_list_t pg_list_nvme = {
+ .pg_count = 1,
+ .pages = {
+ { .id = PAGE_ID_NVME_SMART_HEALTH, .bytes = 512 }
+ }
+};
+
+static smart_page_list_t pg_list_scsi = {
+ .pg_count = 8,
+ .pages = {
+ { .id = PAGE_ID_SCSI_WRITE_ERR, .bytes = 128 },
+ { .id = PAGE_ID_SCSI_READ_ERR, .bytes = 128 },
+ { .id = PAGE_ID_SCSI_VERIFY_ERR, .bytes = 128 },
+ { .id = PAGE_ID_SCSI_NON_MEDIUM_ERR, .bytes = 128 },
+ { .id = PAGE_ID_SCSI_LAST_N_ERR, .bytes = 128 },
+ { .id = PAGE_ID_SCSI_TEMPERATURE, .bytes = 64 },
+ { .id = PAGE_ID_SCSI_START_STOP_CYCLE, .bytes = 128 },
+ { .id = PAGE_ID_SCSI_INFO_EXCEPTION, .bytes = 64 },
+ }
+};
+
+static uint32_t __smart_attribute_max(smart_buf_t *sb);
+static uint32_t __smart_buffer_size(smart_h h);
+static smart_map_t *__smart_map(smart_h h, smart_buf_t *sb);
+static smart_page_list_t *__smart_page_list(smart_h h);
+static int32_t __smart_read_pages(smart_h h, smart_buf_t *sb);
+
+static const char *
+smart_proto_str(smart_protocol_e p)
+{
+
+ switch (p) {
+ case SMART_PROTO_AUTO:
+ return "auto";
+ case SMART_PROTO_ATA:
+ return "ATA";
+ case SMART_PROTO_SCSI:
+ return "SCSI";
+ case SMART_PROTO_NVME:
+ return "NVME";
+ default:
+ return "Unknown";
+ }
+}
+
+smart_h
+smart_open(smart_protocol_e protocol, char *devname)
+{
+ smart_t *s;
+
+ s = device_open(protocol, devname);
+
+ if (s) {
+ dprintf("protocol %s (specified %s%s)\n",
+ smart_proto_str(s->protocol),
+ smart_proto_str(protocol),
+ s->info.tunneled ? ", tunneled ATA" : "");
+ }
+
+ return s;
+}
+
+void
+smart_close(smart_h h)
+{
+
+ device_close(h);
+}
+
+bool
+smart_supported(smart_h h)
+{
+ smart_t *s = h;
+ bool supported = false;
+
+ if (s) {
+ supported = s->info.supported;
+ dprintf("SMART is %ssupported\n", supported ? "" : "not ");
+ }
+
+ return supported;
+}
+
+smart_map_t *
+smart_read(smart_h h)
+{
+ smart_t *s = h;
+ smart_buf_t *sb = NULL;
+ smart_map_t *sm = NULL;
+
+ sb = calloc(1, sizeof(smart_buf_t));
+ if (sb) {
+ sb->protocol = s->protocol;
+
+ /*
+ * Need the page list to calculate the buffer size. If one
+ * isn't specified, get the default based on the protocol.
+ */
+ if (s->pg_list == NULL) {
+ s->pg_list = __smart_page_list(s);
+ if (!s->pg_list) {
+ goto smart_read_out;
+ }
+ }
+
+ sb->b = NULL;
+ sb->bsize = __smart_buffer_size(s);
+
+ if (sb->bsize != 0) {
+ sb->b = malloc(sb->bsize);
+ }
+
+ if (sb->b == NULL) {
+ goto smart_read_out;
+ }
+
+ if (__smart_read_pages(s, sb) < 0) {
+ goto smart_read_out;
+ }
+
+ sb->attr_count = __smart_attribute_max(sb);
+
+ sm = __smart_map(h, sb);
+ if (!sm) {
+ free(sb->b);
+ free(sb);
+ sb = NULL;
+ }
+ }
+
+smart_read_out:
+ if (!sm) {
+ if (sb) {
+ if (sb->b) {
+ free(sb->b);
+ }
+
+ free(sb);
+ }
+ }
+
+ return sm;
+}
+
+void
+smart_free(smart_map_t *sm)
+{
+ smart_buf_t *sb = NULL;
+ uint32_t i;
+
+ if (sm == NULL)
+ return;
+
+ sb = sm->sb;
+
+ if (sb) {
+ if (sb->b) {
+ free(sb->b);
+ sb->b = NULL;
+ }
+
+ free(sb);
+ }
+
+ for (i = 0; i < sm->count; i++) {
+ smart_map_t *tm = sm->attr[i].thresh;
+
+ if (tm) {
+ free(tm);
+ }
+
+ if (sm->attr[i].flags & SMART_ATTR_F_ALLOC) {
+ free((void *)(uintptr_t)sm->attr[i].description);
+ }
+ }
+
+ free(sm);
+}
+
+/*
+ * Format specifier for the various output types
+ * Provides versions to use with libxo and without
+ * TODO some of this is ATA specific
+ */
+#ifndef LIBXO
+# define __smart_print_val(fmt, ...) printf(fmt, ##__VA_ARGS__)
+# define VEND_STR "Vendor\t%s\n"
+# define DEV_STR "Device\t%s\n"
+# define REV_STR "Revision\t%s\n"
+# define SERIAL_STR "Serial\t%s\n"
+# define PAGE_HEX "%#01.1x\t"
+# define PAGE_DEC "%d\t"
+# define ID_HEX "%#01.1x\t"
+# define ID_DEC "%d\t"
+# define RAW_STR "%s"
+# define RAW_HEX "%#01.1x"
+# define RAW_DEC "%d"
+/* Long integer version of the format macro */
+# define RAW_LHEX "%#01.1" PRIx64
+# define RAW_LDEC "%" PRId64
+# define THRESH_HEX "\t%#02.2x\t%#01.1x\t%#01.1x"
+# define THRESH_DEC "\t%d\t%d\t%d"
+# define DESC_STR "%s"
+#else
+# define __smart_print_val(fmt, ...) xo_emit(fmt, ##__VA_ARGS__)
+# define VEND_STR "{L:Vendor}{P:\t}{:vendor/%s}\n"
+# define DEV_STR "{L:Device}{P:\t}{:device/%s}\n"
+# define REV_STR "{L:Revision}{P:\t}{:rev/%s}\n"
+# define SERIAL_STR "{L:Serial}{P:\t}{:serial/%s}\n"
+# define PAGE_HEX "{k:page/%#01.1x}{P:\t}"
+# define PAGE_DEC "{k:page/%d}{P:\t}"
+# define ID_HEX "{k:id/%#01.1x}{P:\t}"
+# define ID_DEC "{k:id/%d}{P:\t}"
+# define RAW_STR "{k:raw/%s}"
+# define RAW_HEX "{k:raw/%#01.1x}"
+# define RAW_DEC "{k:raw/%d}"
+/* Long integer version of the format macro */
+# define RAW_LHEX "{k:raw/%#01.1" PRIx64 "}"
+# define RAW_LDEC "{k:raw/%" PRId64 "}"
+# define THRESH_HEX "{P:\t}{k:flags/%#02.2x}{P:\t}{k:nominal/%#01.1x}{P:\t}{k:worst/%#01.1x}"
+# define THRESH_DEC "{P:\t}{k:flags/%d}{P:\t}{k:nominal/%d}{P:\t}{k:worst/%d}"
+# define DESC_STR "{:description}{P:\t}"
+#endif
+
+#define THRESH_COUNT 3
+
+
+/* Convert an 128-bit unsigned integer to a string */
+static char *
+__smart_u128_str(smart_attr_t *sa)
+{
+ /* Max size is log10(x) = log2(x) / log2(10) ~= log2(x) / 3.322 */
+#define MAX_LEN (128 / 3 + 1 + 1)
+ static char s[MAX_LEN];
+ char *p = s + MAX_LEN - 1;
+ uint32_t *a = (uint32_t *)sa->raw;
+ uint64_t r, d;
+
+ *p-- = '\0';
+
+ do {
+ r = a[3];
+
+ d = r / 10;
+ r = ((r - d * 10) << 32) + a[2];
+ a[3] = d;
+
+ d = r / 10;
+ r = ((r - d * 10) << 32) + a[1];
+ a[2] = d;
+
+ d = r / 10;
+ r = ((r - d * 10) << 32) + a[0];
+ a[1] = d;
+
+ d = r / 10;
+ r = r - d * 10;
+ a[0] = d;
+
+ *p-- = '0' + r;
+ } while (a[0] || a[1] || a[2] || a[3]);
+
+ p++;
+
+ while ((*p == '0') && (p < &s[sizeof(s) - 2]))
+ p++;
+
+ return p;
+}
+
+static void
+__smart_print_thresh(smart_map_t *tm, uint32_t flags)
+{
+ bool do_hex = false;
+
+ if (!tm) {
+ return;
+ }
+
+ if (flags & SMART_OPEN_F_HEX)
+ do_hex = true;
+
+ __smart_print_val(do_hex ? THRESH_HEX : THRESH_DEC,
+ *((uint16_t *)tm->attr[0].raw),
+ *((uint8_t *)tm->attr[1].raw),
+ *((uint8_t *)tm->attr[2].raw));
+}
+
+/* Does the attribute match one requested by the caller? */
+static bool
+__smart_attr_match(smart_matches_t *match, smart_attr_t *attr)
+{
+ uint32_t i;
+
+ assert((match != NULL) && (attr != NULL));
+
+ for (i = 0; i < match->count; i++) {
+ if ((match->m[i].page != -1) && ((uint32_t)match->m[i].page != attr->page))
+ continue;
+
+ if ((uint32_t)match->m[i].id == attr->id)
+ return true;
+ }
+
+ return false;
+}
+
+void
+smart_print(__attribute__((unused)) smart_h h, smart_map_t *sm, smart_matches_t *which, uint32_t flags)
+{
+ uint32_t i;
+ bool do_hex = false, do_descr = false;
+ uint32_t bytes = 0;
+
+ if (!sm) {
+ return;
+ }
+
+ if (flags & SMART_OPEN_F_HEX)
+ do_hex = true;
+ if (flags & SMART_OPEN_F_DESCR)
+ do_descr = true;
+
+#ifdef LIBXO
+ xo_open_container("attributes");
+ xo_open_list("attribute");
+#endif
+ for (i = 0; i < sm->count; i++) {
+ /* If we're printing a specific attribute, is this it? */
+ if ((which != NULL) && !__smart_attr_match(which, &sm->attr[i])) {
+ continue;
+ }
+
+#ifdef LIBXO
+ xo_open_instance("attribute");
+#endif
+ /* Print the page / attribute ID if selecting all attributes */
+ if (which == NULL) {
+ if (do_descr && (sm->attr[i].description != NULL))
+ __smart_print_val(DESC_STR, sm->attr[i].description);
+ else {
+ __smart_print_val(do_hex ? PAGE_HEX : PAGE_DEC, sm->attr[i].page);
+ __smart_print_val(do_hex ? ID_HEX : ID_DEC, sm->attr[i].id);
+ }
+ }
+
+ bytes = sm->attr[i].bytes;
+
+ /* Print the attribute based on its size */
+ if (sm->attr[i].flags & SMART_ATTR_F_STR) {
+ __smart_print_val(RAW_STR, (char *)sm->attr[i].raw);
+ } else if (bytes > 8) {
+ if (do_hex)
+ ;
+ else
+ __smart_print_val(RAW_STR,
+ __smart_u128_str(&sm->attr[i]));
+
+ } else if (bytes > 4) {
+ uint64_t v64 = 0;
+ uint64_t mask = UINT64_MAX;
+
+ memcpy(&v64, sm->attr[i].raw, bytes);
+
+ if (sm->attr[i].flags & SMART_ATTR_F_BE) {
+ v64 = be64toh(v64);
+ } else {
+ v64 = le64toh(v64);
+ }
+
+ mask >>= 8 * (sizeof(uint64_t) - bytes);
+
+ v64 &= mask;
+
+ __smart_print_val(do_hex ? RAW_LHEX : RAW_LDEC, v64);
+
+ } else if (bytes > 2) {
+ uint32_t v32 = 0;
+ uint32_t mask = UINT32_MAX;
+
+ memcpy(&v32, sm->attr[i].raw, bytes);
+
+ if (sm->attr[i].flags & SMART_ATTR_F_BE) {
+ v32 = be32toh(v32);
+ } else {
+ v32 = le32toh(v32);
+ }
+
+ mask >>= 8 * (sizeof(uint32_t) - bytes);
+
+ v32 &= mask;
+
+ __smart_print_val(do_hex ? RAW_HEX : RAW_DEC, v32);
+
+ } else if (bytes > 1) {
+ uint16_t v16 = 0;
+ uint16_t mask = UINT16_MAX;
+
+ memcpy(&v16, sm->attr[i].raw, bytes);
+
+ if (sm->attr[i].flags & SMART_ATTR_F_BE) {
+ v16 = be16toh(v16);
+ } else {
+ v16 = le16toh(v16);
+ }
+
+ mask >>= 8 * (sizeof(uint16_t) - bytes);
+
+ v16 &= mask;
+
+ __smart_print_val(do_hex ? RAW_HEX : RAW_DEC, v16);
+
+ } else if (bytes > 0) {
+ uint8_t v8 = *((uint8_t *)sm->attr[i].raw);
+
+ __smart_print_val(do_hex ? RAW_HEX : RAW_DEC, v8);
+ }
+
+ if ((flags & SMART_OPEN_F_THRESH) && sm->attr[i].thresh) {
+ xo_open_container("threshold");
+ __smart_print_thresh(sm->attr[i].thresh, flags);
+ xo_close_container("threshold");
+ }
+
+ __smart_print_val("\n");
+
+#ifdef LIBXO
+ xo_close_instance("attribute");
+#endif
+ }
+#ifdef LIBXO
+ xo_close_list("attribute");
+ xo_close_container("attributes");
+#endif
+}
+
+void
+smart_print_device_info(smart_h h)
+{
+ smart_t *s = h;
+
+ if (!s) {
+ return;
+ }
+
+ if (*s->info.vendor != '\0')
+ __smart_print_val(VEND_STR, s->info.vendor);
+ if (*s->info.device != '\0')
+ __smart_print_val(DEV_STR, s->info.device);
+ if (*s->info.rev != '\0')
+ __smart_print_val(REV_STR, s->info.device);
+ if (*s->info.serial != '\0')
+ __smart_print_val(SERIAL_STR, s->info.serial);
+}
+
+static uint32_t
+__smart_attr_max_ata(smart_buf_t *sb)
+{
+ uint32_t max = 0;
+
+ if (sb) {
+ max = 30;
+ }
+
+ return max;
+}
+
+static uint32_t
+__smart_attr_max_nvme(smart_buf_t *sb)
+{
+ uint32_t max = 0;
+
+ if (sb) {
+ max = 512;
+ }
+
+ return max;
+}
+
+static uint32_t
+__smart_attr_max_scsi(smart_buf_t *sb)
+{
+ uint32_t max = 0;
+
+ if (sb) {
+ max = 512;
+ }
+
+ return max;
+}
+
+static uint32_t
+__smart_attribute_max(smart_buf_t *sb)
+{
+ uint32_t count = 0;
+
+ if (sb != NULL) {
+ switch (sb->protocol) {
+ case SMART_PROTO_ATA:
+ count = __smart_attr_max_ata(sb);
+ break;
+ case SMART_PROTO_NVME:
+ count = __smart_attr_max_nvme(sb);
+ break;
+ case SMART_PROTO_SCSI:
+ count = __smart_attr_max_scsi(sb);
+ break;
+ default:
+ ;
+ }
+ }
+
+ return count;
+}
+
+/**
+ * Return the total buffer size needed by the protocol's page list
+ */
+static uint32_t
+__smart_buffer_size(smart_h h)
+{
+ smart_t *s = h;
+ uint32_t size = 0;
+
+ if ((s != NULL) && (s->pg_list != NULL)) {
+ smart_page_list_t *plist = s->pg_list;
+ uint32_t p = 0;
+
+ for (p = 0; p < plist->pg_count; p++) {
+ size += plist->pages[p].bytes;
+ }
+ }
+
+ return size;
+}
+
+/*
+ * Map SMART READ DATA threshold attributes
+ *
+ * Read the 3 consecutive values (flags, nominal, and worst)
+ */
+static smart_map_t *
+__smart_map_ata_thresh(uint8_t *b)
+{
+ smart_map_t *sm = NULL;
+
+ sm = malloc(sizeof(smart_map_t) + (THRESH_COUNT * sizeof(smart_attr_t)));
+ if (sm) {
+ uint32_t i;
+
+ sm->count = THRESH_COUNT;
+
+ sm->attr[0].page = 0;
+ sm->attr[0].id = 0;
+ sm->attr[0].bytes = 2;
+ sm->attr[0].flags = 0;
+ sm->attr[0].raw = b;
+ sm->attr[0].thresh = NULL;
+
+ b +=2;
+
+ for (i = 1; i < sm->count; i++) {
+ sm->attr[i].page = 0;
+ sm->attr[i].id = i;
+ sm->attr[i].bytes = 1;
+ sm->attr[i].flags = 0;
+ sm->attr[i].raw = b;
+ sm->attr[i].thresh = NULL;
+
+ b ++;
+ }
+ }
+
+ return sm;
+}
+
+/*
+ * Map SMART READ DATA attributes
+ *
+ * The format for the READ DATA buffer is:
+ * 2 bytes Revision
+ * 360 bytes Attributes (12 bytes each)
+ *
+ * Each attribute consists of:
+ * 1 byte ID
+ * 2 byte Status Flags
+ * 1 byte Nominal value
+ * 1 byte Worst value
+ * 7 byte Raw value
+ * Note that many attributes do not use the entire 7 bytes of the raw value.
+ */
+static void
+__smart_map_ata_read_data(smart_map_t *sm, void *buf, size_t bsize)
+{
+ uint8_t *b = NULL;
+ uint8_t *b_end = NULL;
+ uint32_t max_attr = 0;
+ uint32_t a;
+
+ max_attr = __smart_attr_max_ata(sm->sb);
+ a = sm->count;
+
+ b = buf;
+
+ /* skip revision */
+ b += 2;
+
+ b_end = b + (max_attr * 12);
+ if (b_end > (b + bsize)) {
+ sm->count = 0;
+ return;
+ }
+
+ while (b < b_end) {
+ if (*b != 0) {
+ if ((a - sm->count) >= max_attr) {
+ warnx("More attributes (%d) than fit in map",
+ a - sm->count);
+ break;
+ }
+
+ sm->attr[a].page = PAGE_ID_ATA_SMART_READ_DATA;
+ sm->attr[a].id = b[0];
+ sm->attr[a].description = __smart_ata_desc(
+ PAGE_ID_ATA_SMART_READ_DATA, sm->attr[a].id);
+ sm->attr[a].bytes = 7;
+ sm->attr[a].flags = 0;
+ sm->attr[a].raw = b + 5;
+ sm->attr[a].thresh = __smart_map_ata_thresh(b + 1);
+
+ a++;
+ }
+
+ b += 12;
+ }
+
+ sm->count = a;
+}
+
+static void
+__smart_map_ata_return_status(smart_map_t *sm, void *buf)
+{
+ uint8_t *b = NULL;
+ uint32_t a;
+
+ a = sm->count;
+
+ b = buf;
+
+ sm->attr[a].page = PAGE_ID_ATA_SMART_RET_STATUS;
+ sm->attr[a].id = 0;
+ sm->attr[a].description = __smart_ata_desc(PAGE_ID_ATA_SMART_RET_STATUS,
+ sm->attr[a].id);
+ sm->attr[a].bytes = 1;
+ sm->attr[a].flags = 0;
+ sm->attr[a].raw = b;
+ sm->attr[a].thresh = NULL;
+
+ a++;
+
+ sm->count = a;
+}
+
+static void
+__smart_map_ata(smart_h h, smart_buf_t *sb, smart_map_t *sm)
+{
+ smart_t *s = h;
+ smart_page_list_t *pg_list = NULL;
+ uint8_t *b = NULL;
+ uint32_t p;
+
+ pg_list = s->pg_list;
+ b = sb->b;
+
+ sm->count = 0;
+
+ for (p = 0; p < pg_list->pg_count; p++) {
+ switch (pg_list->pages[p].id) {
+ case PAGE_ID_ATA_SMART_READ_DATA:
+ __smart_map_ata_read_data(sm, b, pg_list->pages[p].bytes);
+ break;
+ case PAGE_ID_ATA_SMART_RET_STATUS:
+ __smart_map_ata_return_status(sm, b);
+ break;
+ }
+
+ b += pg_list->pages[p].bytes;
+ }
+}
+
+#ifndef ARRAYLEN
+#define ARRAYLEN(p) sizeof(p)/sizeof(p[0])
+#endif
+
+#define NVME_VS(mjr,mnr,ter) (((mjr) << 16) | ((mnr) << 8) | (ter))
+#define NVME_VS_1_0 NVME_VS(1,0,0)
+#define NVME_VS_1_1 NVME_VS(1,1,0)
+#define NVME_VS_1_2 NVME_VS(1,2,0)
+#define NVME_VS_1_2_1 NVME_VS(1,2,1)
+#define NVME_VS_1_3 NVME_VS(1,3,0)
+#define NVME_VS_1_4 NVME_VS(1,4,0)
+static struct {
+ uint32_t off; /* buffer offset */
+ uint32_t bytes; /* size in bytes */
+ uint32_t ver; /* first version available */
+ const char *description;
+} __smart_nvme_values[] = {
+ { 0, 1, NVME_VS_1_0, "Critical Warning" },
+ { 1, 2, NVME_VS_1_0, "Composite Temperature" },
+ { 3, 1, NVME_VS_1_0, "Available Spare" },
+ { 4, 1, NVME_VS_1_0, "Available Spare Threshold" },
+ { 5, 1, NVME_VS_1_0, "Percentage Used" },
+ { 6, 1, NVME_VS_1_4, "Endurance Group Critical Warning Summary" },
+ { 32, 16, NVME_VS_1_0, "Data Units Read" },
+ { 48, 16, NVME_VS_1_0, "Data Units Written" },
+ { 64, 16, NVME_VS_1_0, "Host Read Commands" },
+ { 80, 16, NVME_VS_1_0, "Host Write Commands" },
+ { 96, 16, NVME_VS_1_0, "Controller Busy Time" },
+ { 112, 16, NVME_VS_1_0, "Power Cycles" },
+ { 128, 16, NVME_VS_1_0, "Power On Hours" },
+ { 144, 16, NVME_VS_1_0, "Unsafe Shutdowns" },
+ { 160, 16, NVME_VS_1_0, "Media and Data Integrity Errors" },
+ { 176, 16, NVME_VS_1_0, "Number of Error Information Log Entries" },
+ { 192, 4, NVME_VS_1_2, "Warning Composite Temperature Time" },
+ { 196, 4, NVME_VS_1_2, "Critical Composite Temperature Time" },
+ { 200, 2, NVME_VS_1_2, "Temperature Sensor 1" },
+ { 202, 2, NVME_VS_1_2, "Temperature Sensor 2" },
+ { 204, 2, NVME_VS_1_2, "Temperature Sensor 3" },
+ { 206, 2, NVME_VS_1_2, "Temperature Sensor 4" },
+ { 208, 2, NVME_VS_1_2, "Temperature Sensor 5" },
+ { 210, 2, NVME_VS_1_2, "Temperature Sensor 6" },
+ { 212, 2, NVME_VS_1_2, "Temperature Sensor 7" },
+ { 214, 2, NVME_VS_1_2, "Temperature Sensor 8" },
+ { 216, 4, NVME_VS_1_3, "Thermal Management Temperature 1 Transition Count" },
+ { 220, 4, NVME_VS_1_3, "Thermal Management Temperature 2 Transition Count" },
+ { 224, 4, NVME_VS_1_3, "Total Time For Thermal Management Temperature 1" },
+ { 228, 4, NVME_VS_1_3, "Total Time For Thermal Management Temperature 2" },
+};
+
+/**
+ * NVMe doesn't define attribute IDs like ATA does, but we can
+ * approximate this behavior by treating the byte offset as the
+ * attribute ID.
+ */
+static void
+__smart_map_nvme(smart_buf_t *sb, smart_map_t *sm)
+{
+ uint8_t *b = NULL;
+ uint32_t vs = NVME_VS_1_0; // XXX assume device is 1.0
+ uint32_t i, a;
+
+ sm->count = 0;
+ b = sb->b;
+
+ for (i = 0, a = 0; i < ARRAYLEN(__smart_nvme_values); i++) {
+ if (vs >= __smart_nvme_values[i].ver) {
+ sm->attr[a].page = 0x2;
+ sm->attr[a].id = __smart_nvme_values[i].off;
+ sm->attr[a].description = __smart_nvme_values[i].description;
+ sm->attr[a].bytes = __smart_nvme_values[i].bytes;
+ sm->attr[a].flags = 0;
+ sm->attr[a].raw = b + __smart_nvme_values[i].off;
+ sm->attr[a].thresh = NULL;
+
+ a++;
+ }
+ }
+
+ sm->count = a;
+}
+
+/*
+ * Create a SMART map for SCSI error counter pages
+ *
+ * Several SCSI log pages have a similar format for the error counter log
+ * pages
+ */
+static void
+__smart_map_scsi_err_page(smart_map_t *sm, void *b)
+{
+ struct scsi_err_page {
+ uint8_t page_code;
+ uint8_t subpage_code;
+ uint16_t page_length;
+ uint8_t param[];
+ } __attribute__((packed)) *err = b;
+ struct scsi_err_counter_param {
+ uint16_t code;
+ uint8_t format:2,
+ tmc:2,
+ etc:1,
+ tsd:1,
+ :1,
+ du:1;
+ uint8_t length;
+ uint8_t counter[];
+ } __attribute__((packed)) *param = NULL;
+ uint32_t a, p, page_length;
+ const char *cmd = NULL, *desc = NULL;
+
+ switch (err->page_code) {
+ case PAGE_ID_SCSI_WRITE_ERR:
+ cmd = "Write";
+ break;
+ case PAGE_ID_SCSI_READ_ERR:
+ cmd = "Read";
+ break;
+ case PAGE_ID_SCSI_VERIFY_ERR:
+ cmd = "Verify";
+ break;
+ case PAGE_ID_SCSI_NON_MEDIUM_ERR:
+ cmd = "Non-Medium";
+ break;
+ default:
+ fprintf(stderr, "Unknown command %#x\n", err->page_code);
+ cmd = "Unknown";
+ break;
+ }
+
+ a = sm->count;
+
+ p = 0;
+ page_length = be16toh(err->page_length);
+
+ while (p < page_length) {
+ param = (struct scsi_err_counter_param *) (err->param + p);
+
+ sm->attr[a].page = err->page_code;
+ sm->attr[a].id = be16toh(param->code);
+ desc = __smart_scsi_err_desc(sm->attr[a].id);
+ if (desc != NULL) {
+ size_t bytes;
+ char *str;
+
+ bytes = snprintf(NULL, 0, "%s %s", cmd, desc);
+ str = malloc(bytes + 1);
+ if (str != NULL) {
+ snprintf(str, bytes + 1, "%s %s", cmd, desc);
+ sm->attr[a].description = str;
+ sm->attr[a].flags |= SMART_ATTR_F_ALLOC;
+ }
+ }
+ sm->attr[a].bytes = param->length;
+ sm->attr[a].flags = SMART_ATTR_F_BE;
+ sm->attr[a].raw = param->counter;
+ sm->attr[a].thresh = NULL;
+
+ p += 4 + param->length;
+
+ a++;
+ }
+
+ sm->count = a;
+}
+
+static void
+__smart_map_scsi_last_err(smart_map_t *sm, void *b)
+{
+ struct scsi_last_n_error_event_page {
+ uint8_t page_code:6,
+ spf:1,
+ ds:1;
+ uint8_t subpage_code;
+ uint16_t page_length;
+ uint8_t event[];
+ } __attribute__((packed)) *lastn = b;
+ struct scsi_last_n_error_event {
+ uint16_t code;
+ uint8_t format:2,
+ tmc:2,
+ etc:1,
+ tsd:1,
+ :1,
+ du:1;
+ uint8_t length;
+ uint8_t data[];
+ } __attribute__((packed)) *event = NULL;
+ uint32_t a, p, page_length;
+
+ a = sm->count;
+
+ p = 0;
+ page_length = be16toh(lastn->page_length);
+
+ while (p < page_length) {
+ event = (struct scsi_last_n_error_event *) (lastn->event + p);
+
+ sm->attr[a].page = lastn->page_code;
+ sm->attr[a].id = be16toh(event->code);
+ sm->attr[a].bytes = event->length;
+ sm->attr[a].flags = SMART_ATTR_F_BE;
+ sm->attr[a].raw = event->data;
+ sm->attr[a].thresh = NULL;
+
+ p += 4 + event->length;
+
+ a++;
+ }
+
+ sm->count = a;
+}
+
+static void
+__smart_map_scsi_temp(smart_map_t *sm, void *b)
+{
+ struct scsi_temperature_log_page {
+ uint8_t page_code;
+ uint8_t subpage_code;
+ uint16_t page_length;
+ struct scsi_temperature_log_entry {
+ uint16_t code;
+ uint8_t control;
+ uint8_t length;
+ uint8_t rsvd;
+ uint8_t temperature;
+ } param[];
+ } __attribute__((packed)) *temp = b;
+ uint32_t a, p, count;
+
+ count = be16toh(temp->page_length) / sizeof(struct scsi_temperature_log_entry);
+
+ a = sm->count;
+
+ for (p = 0; p < count; p++) {
+ uint16_t code = be16toh(temp->param[p].code);
+ switch (code) {
+ case 0:
+ case 1:
+ sm->attr[a].page = temp->page_code;
+ sm->attr[a].id = be16toh(temp->param[p].code);
+ sm->attr[a].description = code == 0 ? "Temperature" : "Reference Temperature";
+ sm->attr[a].bytes = 1;
+ sm->attr[a].flags = 0;
+ sm->attr[a].raw = &(temp->param[p].temperature);
+ sm->attr[a].thresh = NULL;
+ a++;
+ break;
+ default:
+ break;
+ }
+ }
+
+ sm->count = a;
+}
+
+static void
+__smart_map_scsi_start_stop(smart_map_t *sm, void *b)
+{
+ struct scsi_start_stop_page {
+ uint8_t page_code;
+#define START_STOP_CODE_DATE_MFG 0x0001
+#define START_STOP_CODE_DATE_ACCTN 0x0002
+#define START_STOP_CODE_CYCLES_LIFE 0x0003
+#define START_STOP_CODE_CYCLES_ACCUM 0x0004
+#define START_STOP_CODE_LOAD_LIFE 0x0005
+#define START_STOP_CODE_LOAD_ACCUM 0x0006
+ uint8_t subpage_code;
+ uint16_t page_length;
+ uint8_t param[];
+ } __attribute__((packed)) *sstop = b;
+ struct scsi_start_stop_param {
+ uint16_t code;
+ uint8_t format:2,
+ tmc:2,
+ etc:1,
+ tsd:1,
+ :1,
+ du:1;
+ uint8_t length;
+ uint8_t data[];
+ } __attribute__((packed)) *param;
+ uint32_t a, p, page_length;
+
+ a = sm->count;
+
+ p = 0;
+ page_length = be16toh(sstop->page_length);
+
+ while (p < page_length) {
+ param = (struct scsi_start_stop_param *) (sstop->param + p);
+
+ sm->attr[a].page = sstop->page_code;
+ sm->attr[a].id = be16toh(param->code);
+ sm->attr[a].bytes = param->length;
+
+ switch (sm->attr[a].id) {
+ case START_STOP_CODE_DATE_MFG:
+ sm->attr[a].description = "Date of Manufacture";
+ sm->attr[a].flags = SMART_ATTR_F_STR;
+ break;
+ case START_STOP_CODE_DATE_ACCTN:
+ sm->attr[a].description = "Accounting Date";
+ sm->attr[a].flags = SMART_ATTR_F_STR;
+ break;
+ case START_STOP_CODE_CYCLES_LIFE:
+ sm->attr[a].description = "Specified Cycle Count Over Device Lifetime";
+ sm->attr[a].flags = SMART_ATTR_F_BE;
+ break;
+ case START_STOP_CODE_CYCLES_ACCUM:
+ sm->attr[a].description = "Accumulated Start-Stop Cycles";
+ sm->attr[a].flags = SMART_ATTR_F_BE;
+ break;
+ case START_STOP_CODE_LOAD_LIFE:
+ sm->attr[a].description = "Specified Load-Unload Count Over Device Lifetime";
+ sm->attr[a].flags = SMART_ATTR_F_BE;
+ break;
+ case START_STOP_CODE_LOAD_ACCUM:
+ sm->attr[a].description = "Accumulated Load-Unload Cycles";
+ sm->attr[a].flags = SMART_ATTR_F_BE;
+ break;
+ }
+
+ sm->attr[a].raw = param->data;
+ sm->attr[a].thresh = NULL;
+
+ p += 4 + param->length;
+
+ a++;
+ }
+
+ sm->count = a;
+}
+
+static void
+__smart_map_scsi_info_exception(smart_map_t *sm, void *b)
+{
+ struct scsi_info_exception_log_page {
+ uint8_t page_code;
+ uint8_t subpage_code;
+ uint16_t page_length;
+ uint8_t param[];
+ } __attribute__((packed)) *ie = b;
+ struct scsi_ie_param {
+ uint16_t code;
+ uint8_t control;
+ uint8_t length;
+ uint8_t asc; /* IE Additional Sense Code */
+ uint8_t ascq; /* IE Additional Sense Code Qualifier */
+ uint8_t temp_recent;
+ uint8_t temp_trip_point;
+ uint8_t temp_max;
+ } __attribute__((packed)) *param;
+ uint32_t a, p, page_length;
+
+ a = sm->count;
+
+ p = 0;
+ page_length = be16toh(ie->page_length);
+
+ while (p < page_length) {
+ param = (struct scsi_ie_param *)(ie->param + p);
+
+ p += 4 + param->length;
+
+ sm->attr[a].page = ie->page_code;
+ sm->attr[a].id = offsetof(struct scsi_ie_param, asc);
+ sm->attr[a].description = "Informational Exception ASC";
+ sm->attr[a].bytes = 1;
+ sm->attr[a].flags = 0;
+ sm->attr[a].raw = &param->asc;
+ sm->attr[a].thresh = NULL;
+ a++;
+
+ sm->attr[a].page = ie->page_code;
+ sm->attr[a].id = offsetof(struct scsi_ie_param, ascq);
+ sm->attr[a].description = "Informational Exception ASCQ";
+ sm->attr[a].bytes = 1;
+ sm->attr[a].flags = 0;
+ sm->attr[a].raw = &param->ascq;
+ sm->attr[a].thresh = NULL;
+ a++;
+
+ sm->attr[a].page = ie->page_code;
+ sm->attr[a].id = offsetof(struct scsi_ie_param, temp_recent);
+ sm->attr[a].description = "Informational Exception Most recent temperature";
+ sm->attr[a].bytes = 1;
+ sm->attr[a].flags = 0;
+ sm->attr[a].raw = &param->temp_recent;
+ sm->attr[a].thresh = NULL;
+ a++;
+
+ sm->attr[a].page = ie->page_code;
+ sm->attr[a].id = offsetof(struct scsi_ie_param, temp_trip_point);
+ sm->attr[a].description = "Informational Exception Vendor HDA temperature trip point";
+ sm->attr[a].bytes = 1;
+ sm->attr[a].flags = 0;
+ sm->attr[a].raw = &param->temp_trip_point;
+ sm->attr[a].thresh = NULL;
+ a++;
+
+ sm->attr[a].page = ie->page_code;
+ sm->attr[a].id = offsetof(struct scsi_ie_param, temp_max);
+ sm->attr[a].description = "Informational Exception Maximum temperature";
+ sm->attr[a].bytes = 1;
+ sm->attr[a].flags = 0;
+ sm->attr[a].raw = &param->temp_max;
+ sm->attr[a].thresh = NULL;
+ a++;
+ }
+
+ sm->count = a;
+}
+
+/*
+ * Create a map based on the page list
+ */
+static void
+__smart_map_scsi(smart_h h, smart_buf_t *sb, smart_map_t *sm)
+{
+ smart_t *s = h;
+ smart_page_list_t *pg_list = NULL;
+ uint8_t *b = NULL;
+ uint32_t p;
+
+ pg_list = s->pg_list;
+ b = sb->b;
+
+ sm->count = 0;
+
+ for (p = 0; p < pg_list->pg_count; p++) {
+ switch (pg_list->pages[p].id) {
+ case PAGE_ID_SCSI_WRITE_ERR:
+ case PAGE_ID_SCSI_READ_ERR:
+ case PAGE_ID_SCSI_VERIFY_ERR:
+ case PAGE_ID_SCSI_NON_MEDIUM_ERR:
+ __smart_map_scsi_err_page(sm, b);
+ break;
+ case PAGE_ID_SCSI_LAST_N_ERR:
+ __smart_map_scsi_last_err(sm, b);
+ break;
+ case PAGE_ID_SCSI_TEMPERATURE:
+ __smart_map_scsi_temp(sm, b);
+ break;
+ case PAGE_ID_SCSI_START_STOP_CYCLE:
+ __smart_map_scsi_start_stop(sm, b);
+ break;
+ case PAGE_ID_SCSI_INFO_EXCEPTION:
+ __smart_map_scsi_info_exception(sm, b);
+ break;
+ }
+
+ b += pg_list->pages[p].bytes;
+ }
+}
+
+/**
+ * Create a map of SMART values
+ */
+static void
+__smart_attribute_map(smart_h h, smart_buf_t *sb, smart_map_t *sm)
+{
+
+ if (!sb || !sm) {
+ return;
+ }
+
+ switch (sb->protocol) {
+ case SMART_PROTO_ATA:
+ __smart_map_ata(h, sb, sm);
+ break;
+ case SMART_PROTO_NVME:
+ __smart_map_nvme(sb, sm);
+ break;
+ case SMART_PROTO_SCSI:
+ __smart_map_scsi(h, sb, sm);
+ break;
+ default:
+ sm->count = 0;
+ }
+}
+
+static smart_map_t *
+__smart_map(smart_h h, smart_buf_t *sb)
+{
+ smart_map_t *sm = NULL;
+ uint32_t max = 0;
+
+ max = sb->attr_count;
+ if (max == 0) {
+ warnx("Attribute count is zero?!?");
+ return NULL;
+ }
+
+ sm = malloc(sizeof(smart_map_t) + (max * sizeof(smart_attr_t)));
+ if (sm) {
+ memset(sm, 0, sizeof(smart_map_t) + (max * sizeof(smart_attr_t)));
+ sm->sb = sb;
+
+ /* count starts as the max but is adjusted to reflect the actual number */
+ sm->count = max;
+
+ __smart_attribute_map(h, sb, sm);
+ }
+
+ return sm;
+}
+
+typedef struct {
+ uint8_t page_code;
+ uint8_t subpage_code;
+ uint16_t page_length;
+ uint8_t supported_pages[];
+} __attribute__((packed)) scsi_supported_log_pages;
+
+static smart_page_list_t *
+__smart_page_list_scsi(smart_t *s)
+{
+ smart_page_list_t *pg_list = NULL;
+ scsi_supported_log_pages *b = NULL;
+ uint32_t bsize = 68; /* 4 byte header + 63 entries + 1 just cuz */
+ int32_t rc;
+
+ b = malloc(bsize);
+ if (!b) {
+ return NULL;
+ }
+
+ /* Supported Pages page ID is 0 */
+ rc = device_read_log(s, PAGE_ID_SCSI_SUPPORTED_PAGES, (uint8_t *)b,
+ bsize);
+ if (rc < 0) {
+ fprintf(stderr, "Read Supported Log Pages failed\n");
+ } else {
+ uint8_t *supported_page = b->supported_pages;
+ uint32_t n_supported = be16toh(b->page_length);
+ uint32_t pg, p, pmax = pg_list_scsi.pg_count;
+
+ /* Build a page list using only pages the device supports */
+ pg_list = malloc(sizeof(pg_list_scsi));
+ if (pg_list == NULL) {
+ n_supported = 0;
+ } else {
+ pg_list->pg_count = 0;
+ }
+
+ /*
+ * Loop through all supported pages looking for those related
+ * to SMART. The below assumes the supported page list from the
+ * device and in pg_lsit_scsi are sorted in increasing order.
+ */
+ dprintf("Supported SCSI pages:\n");
+ for (pg = 0, p = 0; (pg < n_supported) && (p < pmax); pg++) {
+ dprintf("\t[%u] = %#x\n", pg, supported_page[pg]);
+ while ((supported_page[pg] > pg_list_scsi.pages[p].id) &&
+ (p < pmax)) {
+ p++;
+ }
+
+ if (supported_page[pg] == pg_list_scsi.pages[p].id) {
+ pg_list->pages[pg_list->pg_count] = pg_list_scsi.pages[p];
+ pg_list->pg_count++;
+ p++;
+ }
+ }
+ }
+
+ free(b);
+
+ return pg_list;
+}
+
+static smart_page_list_t *
+__smart_page_list(smart_h h)
+{
+ smart_t *s = h;
+ smart_page_list_t *pg_list = NULL;
+
+ if (!s) {
+ return NULL;
+ }
+
+ switch (s->protocol) {
+ case SMART_PROTO_ATA:
+ pg_list = &pg_list_ata;
+ break;
+ case SMART_PROTO_NVME:
+ pg_list = &pg_list_nvme;
+ break;
+ case SMART_PROTO_SCSI:
+ pg_list = __smart_page_list_scsi(s);
+ break;
+ default:
+ pg_list = NULL;
+ }
+
+ return pg_list;
+}
+
+static int32_t
+__smart_read_pages(smart_h h, smart_buf_t *sb)
+{
+ smart_t *s = h;
+ smart_page_list_t *plist = NULL;
+ uint8_t *buf = NULL;
+ int32_t rc = 0;
+ uint32_t p = 0;
+
+ plist = s->pg_list;
+
+ buf = sb->b;
+
+ for (p = 0; p < s->pg_list->pg_count; p++) {
+ memset(buf, 0, plist->pages[p].bytes);
+ rc = device_read_log(h, plist->pages[p].id, buf, plist->pages[p].bytes);
+ if (rc) {
+ dprintf("bad read (%d) from page %#x (bytes=%zu)\n", rc,
+ plist->pages[p].id, plist->pages[p].bytes);
+ break;
+ }
+
+ buf += plist->pages[p].bytes;
+ }
+
+ return rc;
+}
diff --git a/contrib/smart/libsmart.h b/contrib/smart/libsmart.h
new file mode 100644
index 000000000000..60346f3b3a70
--- /dev/null
+++ b/contrib/smart/libsmart.h
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2016-2021 Chuck Tuffli <chuck@tuffli.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef _LIBSMART_H
+#define _LIBSMART_H
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+/*
+ * libsmart uses a common model for SMART data (a.k.a. "attributes") across
+ * storage protocols. Each health value consists of:
+ * - The identifier of the log page containing this attribute
+ * - The attribute's identifier
+ * - A description of the attribute
+ * - A pointer to the raw data
+ * - The attribute's size in bytes
+ *
+ * This model most closely resembles SCSI's native representation, but it
+ * can represent ATA and NVMe with the following substitutions:
+ * - ATA : use the Command Feature field value for the log page ID
+ * - NVMe : use the field's starting byte offset for the attribute ID
+ *
+ * libsmart returns a "map" to the SMART/health data read from a device
+ * in the smart_map_t structure. The map consists of:
+ * - A variable-length array of attributes
+ * - The length of the array
+ * - The raw data read from the device
+ *
+ * Consumers of the map will typically iterate through the array of attributes
+ * to print or otherwise process the health data.
+ */
+
+/*
+ * A smart handle is an opaque reference to the device
+ */
+typedef void * smart_h;
+
+typedef enum {
+ SMART_PROTO_AUTO,
+ SMART_PROTO_ATA,
+ SMART_PROTO_SCSI,
+ SMART_PROTO_NVME,
+ SMART_PROTO_MAX
+} smart_protocol_e;
+
+/*
+ * A smart buffer contains the raw data returned from the protocol-specific
+ * health command.
+ */
+typedef struct {
+ smart_protocol_e protocol;
+ void *b; // buffer of raw data
+ size_t bsize; // buffer size
+ uint32_t attr_count; // number of SMART attributes
+} smart_buf_t;
+
+struct smart_map_s;
+
+/*
+ * A smart attribute is an individual health data element
+ */
+typedef struct smart_attr_s {
+ uint32_t page;
+ uint32_t id;
+ const char *description; /* human readable description */
+ uint32_t bytes;
+ uint32_t flags;
+#define SMART_ATTR_F_BE 0x00000001 /* Attribute is big-endian */
+#define SMART_ATTR_F_STR 0x00000002 /* Attribute is a string */
+#define SMART_ATTR_F_ALLOC 0x00000004 /* Attribute description dynamically allocated */
+ void *raw;
+ struct smart_map_s *thresh; /* Threshold values (if any) */
+} smart_attr_t;
+
+/*
+ * A smart map is the collection of health data elements from the device
+ */
+typedef struct smart_map_s {
+ smart_buf_t *sb;
+ uint32_t count; /* Number of attributes */
+ smart_attr_t attr[]; /* Array of attributes */
+} smart_map_t;
+
+#define SMART_OPEN_F_HEX 0x1 /* Print values in hexadecimal */
+#define SMART_OPEN_F_THRESH 0x2 /* Print threshold values */
+#define SMART_OPEN_F_DESCR 0x4 /* Print textual description */
+
+/* SMART attribute to match */
+typedef struct smart_match_s {
+ int32_t page;
+ int32_t id;
+} smart_match_t;
+
+/* List of SMART attribute(s) to match */
+typedef struct smart_matches_s {
+ uint32_t count;
+ smart_match_t m[];
+} smart_matches_t;
+
+/**
+ * Connect to a device to read SMART data
+ *
+ * @param p The desired protocol or "auto" to automatically detect it
+ * @param devname The device name to open
+ *
+ * @return An opaque handle or NULL on failure
+ */
+smart_h smart_open(smart_protocol_e p, char *devname);
+/**
+ * Close device connection
+ *
+ * @param handle The handle returned from smart_open()
+ *
+ * @return None
+ */
+void smart_close(smart_h);
+/**
+ * Does the device support SMART/health data?
+ *
+ * @param handle The handle returned from smart_open()
+ *
+ * @return true / false
+ */
+bool smart_supported(smart_h);
+/**
+ * Read SMART/health data from the device
+ *
+ * @param handle The handle returned from smart_open()
+ *
+ * @return a pointer to the SMART map or NULL on failure
+ */
+smart_map_t *smart_read(smart_h);
+/**
+ * Free memory associated with the health data read from the device
+ *
+ * @param map Pointer returned from smart_read()
+ *
+ * @return None
+ */
+void smart_free(smart_map_t *);
+/**
+ * Print health data matching the desired attributes
+ *
+ * @param handle The handle returned from smart_open()
+ * @param map Pointer returned from smart_read()
+ * @param which Pointer to attributes to match or NULL to match all
+ * @param flags Control display of attributes (hexadecimal, description, ...
+ *
+ * @return None
+ */
+void smart_print(smart_h, smart_map_t *, smart_matches_t *, uint32_t);
+/**
+ * Print high-level device information
+ *
+ * @param handle The handle returned from smart_open()
+ *
+ * @return None
+ */
+void smart_print_device_info(smart_h);
+
+#endif
diff --git a/contrib/smart/libsmart_desc.c b/contrib/smart/libsmart_desc.c
new file mode 100644
index 000000000000..bcfb31d66922
--- /dev/null
+++ b/contrib/smart/libsmart_desc.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2021 Chuck Tuffli <chuck@tuffli.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <stddef.h>
+
+#include "libsmart.h"
+#include "libsmart_priv.h"
+
+/* Strings from "SMART Attribute Descriptions" (SAD) */
+static const char *
+desc_ata_data[] = {
+ [1] = "Read Error Rate",
+ [2] = "Throughput Performance",
+ [3] = "Spin-Up Time",
+ [4] = "Start/Stop Count",
+ [5] = "Reallocated Sectors Count",
+ [6] = "Read Channel Margin",
+ [7] = "Seek Error Rate",
+ [8] = "Seek Time Performance",
+ [9] = "Power-On Hours",
+ [10] = "Spin Retry Count",
+ [11] = "Calibration Retry Count",
+ [12] = "Power Cycle Count",
+ [13] = "Soft Read Error Rate",
+ [22] = "Current Helium Level", /* HGST */
+ [170] = "Available Reserved Space", /* Intel */
+ [171] = "SSD Program Fail", /* Kingston? */
+ [172] = "SSD Erase Fail Count", /* Kingston? */
+ [173] = "SSD Wear Leveling Count", /* HPE SSD Endurance Limit */
+ [174] = "Unexpected Power Loss Count", /* Intel */
+ [175] = "Power Loss Protection Failure", /* Intel */
+ [176] = "Erase Fail Count (chip)",
+ [177] = "Wear Range Delta",
+ [179] = "Used Reserved Block Count Total",
+/* [180] = HPE, Seagate, Intel differences */
+ [181] = "Non-4K Aligned Access Count", /* Micron. Conflict Kingston */
+ [182] = "Erase Fail Count",
+ [183] = "Runtime Bad Block",
+ [184] = "End-to-End Error",
+ [185] = "Head Stability", /* WD */
+ [186] = "Induced Op-Vibration Detection", /* WD */
+ [187] = "Reported Uncorrectable Errors",
+ [188] = "Command Timeout",
+ [189] = "High Fly Writes",
+ [190] = "Airflow Temperature", /* WDC, HPE conflict */
+ [191] = "G-Sense Error Rate",
+ [192] = "Power-Off Count", /* HPE, Seagate */
+ [193] = "Load/Unload Cycle Count",
+ [194] = "Temperature Celsius",
+ [195] = "Hardware ECC Recovered",
+ [196] = "Reallocation Event Count",
+ [197] = "Current Pending Sector Count",
+ [198] = "Uncorrectable Sector Count", /* Fujitsu */
+ [199] = "UltraDMA CRC Error Count",
+ [200] = "Write Error Rate",
+ [201] = "Soft Read Error Rate",
+ [202] = "Data Address Mark Errors",
+ [203] = "Run Out Cancel",
+ [204] = "Soft ECC Correction",
+ [205] = "Thermal Asperity Rate",
+ [206] = "Flying Height",
+ [207] = "Spin High Current",
+ [208] = "Spin Buzz",
+ [209] = "Offline Seek Performnce",
+ [210] = "Vibration, During Write", /* Maxtor */
+ [211] = "Vibration During Write", /* Acronis */
+ [212] = "Shock During Write", /* Acronis */
+ [220] = "Disk Shift",
+ [221] = "G-Sense Error Rate",
+ [222] = "Loaded Hours",
+ [223] = "Load/Unload Retry Count",
+ [224] = "Load Friction",
+ [225] = "Load/Unload Cycle Count",
+ [226] = "Load-in Time",
+ [227] = "Torque Amplification Count",
+ [228] = "Power-off Retract Cycle",
+ [230] = "GMR Head Amplitude Drive Life Protection Status",
+ [231] = "Temperature SSD Life Left", /* Kingston */
+ [232] = "Endurance Remaining", /* Multiple conflict */
+ [233] = "Power-On Hours", /* Multiple conflict */
+ [234] = "Average Erase Count", /* Multiple conflict */
+ [235] = "Good Block Count", /* Multiple conflict */
+ [240] = "Head Flying Hours",
+ [241] = "Total LBAs Written",
+ [242] = "Total LBAs Read",
+ [243] = "Total LBAs Written Expanded", /* Multiple conflict */
+ [244] = "Total LBAs Read Expanded", /* Multiple conflict */
+ [250] = "Read Error Rate",
+ [251] = "Minimum Spares Remaining",
+ [252] = "Newly Added Bad Flash Block",
+ [254] = "Free Fall Protection"
+};
+
+const char *
+__smart_ata_desc(uint32_t page, uint32_t id)
+{
+ const char *desc = NULL;
+
+ switch (page) {
+ case PAGE_ID_ATA_SMART_READ_DATA:
+ if (desc_ata_data[id] != NULL)
+ desc = desc_ata_data[id];
+ break;
+ case PAGE_ID_ATA_SMART_RET_STATUS:
+ desc = "SMART Status";
+ break;
+ default:
+ ;
+ }
+
+ return (desc);
+}
+
+const char *
+__smart_scsi_err_desc(uint32_t id)
+{
+ const char *param = NULL;
+
+ switch (id) {
+ case 0:
+ param = "Errors corrected without substantial delay";
+ break;
+ case 1:
+ param = "Errors corrected with possible delays";
+ break;
+ case 2:
+ param = "Total retries";
+ break;
+ case 3:
+ param = "Total errors corrected";
+ break;
+ case 4:
+ param = "Total times correction algorithm processed";
+ break;
+ case 5:
+ param = "Total bytes processed";
+ break;
+ case 6:
+ param = "Total uncorrected errors";
+ break;
+ default:
+ return (NULL);
+ }
+
+ return (param);
+}
diff --git a/contrib/smart/libsmart_dev.h b/contrib/smart/libsmart_dev.h
new file mode 100644
index 000000000000..bbf028e73712
--- /dev/null
+++ b/contrib/smart/libsmart_dev.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2017-2021 Chuck Tuffli <chuck@tuffli.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef _LIBSMART_DEV_H
+#define _LIBSMART_DEV_H
+
+/**
+ * Open a device to gather SMART information
+ *
+ * The call performs OS specific functions necessary to prepare the device
+ * to receive read log requests.
+ *
+ * Although opaque to the user, the handle must be a pointer to a structure
+ * with the first member being struct smart_s. The remaining members are OS
+ * specific and are not used by the library.
+ *
+ * @param protocol The desired protocol or "auto" to automatically detect it
+ * @param devname The device name to open
+ *
+ * @return An opaque handle to the device or NULL on failure
+ */
+extern smart_h device_open(smart_protocol_e, char *);
+
+/**
+ * Close a device and release the associated resources
+ *
+ * @param handle The handle returned from device_open()
+ *
+ * @return None
+ */
+extern void device_close(smart_h);
+
+/**
+ * Read the log page
+ *
+ * This call reads the specified log page in the protocol specific manner
+ * needed by the device. The results are placed in the provided buffer.
+ *
+ * @param h SMART handle returned from device_open()
+ * @param page The log page ID
+ * @param buf Pointer to buffer containing the results of the read
+ * @param bsize Size of the buffer in bytes
+ *
+ * @return Zero on success, errno on failure
+ */
+extern int32_t device_read_log(smart_h, uint32_t, void *, size_t);
+
+#endif /* !_LIBSMART_DEV_H */
diff --git a/contrib/smart/libsmart_priv.h b/contrib/smart/libsmart_priv.h
new file mode 100644
index 000000000000..f29fc1e1e033
--- /dev/null
+++ b/contrib/smart/libsmart_priv.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2016-2021 Chuck Tuffli <chuck@tuffli.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef _LIBSMART_PRIV_H
+#define _LIBSMART_PRIV_H
+
+/* OS-independent structures and definitions internal to libsmart */
+
+#define PAGE_ID_ATA_SMART_READ_DATA 0xd0 /* SMART Read Data */
+#define PAGE_ID_ATA_SMART_RET_STATUS 0xda /* SMART Return Status */
+
+#define PAGE_ID_SCSI_SUPPORTED_PAGES 0x00
+#define PAGE_ID_SCSI_WRITE_ERR 0x02 /* Write Error counter */
+#define PAGE_ID_SCSI_READ_ERR 0x03 /* Read Error counter */
+#define PAGE_ID_SCSI_VERIFY_ERR 0x05 /* Verify Error counter */
+#define PAGE_ID_SCSI_NON_MEDIUM_ERR 0x06 /* Non-Medium Error */
+#define PAGE_ID_SCSI_LAST_N_ERR 0x07 /* Last n Error events */
+#define PAGE_ID_SCSI_TEMPERATURE 0x0d /* Temperature */
+#define PAGE_ID_SCSI_START_STOP_CYCLE 0x0e /* Start-Stop Cycle counter */
+#define PAGE_ID_SCSI_INFO_EXCEPTION 0x2f /* Informational Exceptions */
+
+extern bool do_debug;
+
+#define dprintf(f, ...) if (do_debug) fprintf(stderr, "dbg: " f, ## __VA_ARGS__)
+
+/* General information about the device */
+typedef struct smart_info_s {
+ /* device supports SMART */
+ uint32_t supported:1,
+ /* storage protocol is tunneled (e.g. ATA inside SCSI) */
+ tunneled:1,
+ :30;
+ /*
+ * Device-provided information, including
+ * - vendor name
+ * - device / model
+ * - firmware revision
+ * - serial number
+ * Protocols may provide a subset of this information
+ */
+ char vendor[16], device[48], rev[16], serial[32];
+} smart_info_t;
+
+/* List of pages providing SMART/health data */
+typedef struct smart_page_list_s {
+ uint32_t pg_count;
+ struct {
+ uint32_t id;
+ size_t bytes;
+ } pages[];
+} smart_page_list_t;
+
+/*
+ * The device handle (i.e. smart_h) is an opaque pointer to memory containing
+ * device/OS independent and dependent data. The library uses type punning to
+ * isolate the OS-independent portion (struct smart_s) from the OS-dependent
+ * details. Because of this, the device layer allocates and frees this memory.
+ */
+typedef struct smart_s {
+ smart_protocol_e protocol;
+ smart_info_t info;
+ smart_page_list_t *pg_list;
+ /* Device / OS specific follows this structure */
+} smart_t;
+
+/* Return a textual description of the ATA attribute */
+const char * __smart_ata_desc(uint32_t page, uint32_t id);
+/* Return a textual description of the SCSI error attribute */
+const char * __smart_scsi_err_desc(uint32_t id);
+
+#endif
diff --git a/contrib/smart/smart.8 b/contrib/smart/smart.8
new file mode 100644
index 000000000000..3215ff890001
--- /dev/null
+++ b/contrib/smart/smart.8
@@ -0,0 +1,245 @@
+.\"
+.\" SPDX-License-Identifier: BSD-2-Clause
+.\"
+.\" Copyright (c) 2021-2026 Chuck Tuffli
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" Note: The date here should be updated whenever a non-trivial
+.\" change is made to the manual page.
+.Dd February 14, 2026
+.Dt SMART 8
+.Os
+.Sh NAME
+.Nm smart ,
+.Nm diskhealth
+.Nd monitor disk health from a storage device via SMART
+.Sh SYNOPSIS
+.Nm
+.Op Fl dhitvx
+.Oo Fl a Ar page:attribute Ns Oo , Ns Ar page:attribute Oc Ns ... Oc
+.Op Fl Fl debug
+.Ar device
+.Nm diskhealth
+.Op Fl Dhitvx
+.Oo Fl a Ar page:attribute Ns Oo , Ns Ar page:attribute Oc Ns ... Oc
+.Op Fl Fl debug
+.Ar device
+.Sh DESCRIPTION
+The
+.Nm
+command allows the user to monitor the various information reported
+by Self-Monitoring, Analysis and Reporting Technology (SMART) present
+on most ATA, SCSI, and NVMe storage media.
+Because the structure of this information varies across protocols,
+.Nm
+normalizes entries using the format:
+.Bd -literal
+ <Page ID> <Attribute ID> <Value> <Thresholds>
+.Ed
+.Pp
+Fields are tab-delimited by default, but the command can output
+data in any format supported by
+.Xr libxo 3 .
+.Pp
+Because ATA does not have log pages,
+.Nm
+uses the Command Feature field value in place of the log page ID.
+For SMART READ DATA, this value is 208 / 0xd0.
+Note that devices choose which attribute ID values they support, their
+descriptions, and the format of the data.
+The three values displayed with the
+.Fl Fl threshold
+option are:
+.Pp
+.Bl -dash -compact -offset indent
+.It
+Status flags (byte offset 1, 2 bytes)
+.It
+Nominal attribute value (byte offset 3, 1 byte)
+.It
+Worst Ever attribute value (byte offset 4, 1 byte)
+.El
+.Pp
+Additionally,
+.Nm
+reports the value of the SMART STATUS command (Command Feature field
+value 218 / 0xda).
+As this command does not return any data,
+the command represents this entry with a synthetic attribute
+ID of 0, and it uses the command status (0 or 1) as the attribute
+value.
+.Pp
+NVMe devices support the SMART/Health log page (Page ID 2 / 0x2).
+The data returned in this log page is not structured as attribute IDs.
+Instead,
+.Nm
+uses the byte offset of each field as the attribute ID.
+For example,
+byte 3 is the Available Spare.
+Thus, for NVMe, attribute ID 3 is
+Available Spare.
+Note that NVMe health data does not include threshold
+values, and as a result, the command will ignore the
+.Fl Fl threshold
+option.
+.Pp
+SCSI devices can support a number of log pages which report drive
+health.
+The command will report the following pages:
+.Pp
+.Bl -dash -compact -offset indent
+.It
+Write Errors (Page ID 2 / 0x2)
+.It
+Read Errors (Page ID 3 / 0x3)
+.It
+Verify Errors (Page ID 5 / 0x5)
+.It
+Non-medium Errors (Page ID 6 / 0x6)
+.It
+Last N Errors (Page ID 7 / 0x7)
+.It
+Temperature (Page ID 13 / 0xd)
+.It
+Start-stop Cycles (Page ID 14 / 0xe)
+.It
+Informational Exceptions (Page ID 47 / 0x2f)
+.El
+.Pp
+Note that all log pages are optional, and a particular drive
+may not support all these pages.
+For SCSI devices, the Attribute ID
+maps to the SCSI parameter code defined by the command.
+Parameter
+codes are integer values from 0 to N, and, by themselves, are ambiguous
+outside the context of a particular log page.
+Note that SCSI health data
+does not include threshold values, and as a result, the command will
+ignore the
+.Fl Fl threshold
+option.
+.Pp
+The following options are available:
+.Bl -tag -width "-d argument"
+.It Fl a Ar page:attribute , Fl Fl attribute= Ns Ar page:attribute
+A comma-separated list of attributes to display.
+If page is missing, display the matching attribute from any page.
+.It Fl d , Fl Fl decode
+Decode the attribute ID values.
+This is the default when invoked as
+.Nm diskhealth .
+.It Fl D , Fl Fl no-decode
+Do not decode the attribute ID values.
+This is the default when invoked as
+.Nm .
+.It Fl h , Fl Fl help
+Prints a usage message and exits.
+.It Fl i , Fl Fl info
+Print general device information.
+.It Fl t , Fl Fl threshold
+Also print the threshold values.
+.It Fl v , Fl Fl version
+Print the version and copyright.
+.It Fl x , Fl Fl hex
+Print the values in hexadecimal.
+.It Ar device
+An explicit device path
+.Pq Pa /dev/ada0
+or GEOM provider
+.Pq Pa ada0
+.
+.El
+.El
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+Print all SMART READ DATA and SMART STATUS including the
+threshold values for ATA drive ada0.
+.Pp
+.Dl # smart -t ada0
+.Pp
+Print only attribute ID 5 ("Reallocated Sectors Count") for
+ATA drive ada0.
+.Pp
+.Dl # smart -a 5 ada0
+.Pp
+Print attribute IDs 5 ("Reallocated Sectors Count") and 171
+("SSD Program Fail") for ATA drive ada0.
+.Pp
+.Dl # smart -a 5,171 ada0
+.Pp
+Print all health pages supported by SCSI device da0 including:
+.Bl -dash -compact -offset indent
+.It
+Write Errors
+.It
+Read Errors
+.It
+Verify Errors
+.It
+Non-medium Errors
+.It
+Last N Errors
+.It
+Temperature
+.It
+Start-stop Cycles
+.It
+Informational Exceptions
+.El
+.Pp
+.Dl # smart da0
+.Pp
+Print all Health log page entries in hexadecimal for NVMe
+device nda0.
+.Pp
+.Dl # smart -x nda0
+.Sh DIAGNOSTICS
+The command may fail for one of the following reasons:
+.Bl -diag
+.It "No output displayed"
+The device does not support health data.
+.It "CAMGETPASSTHRU ioctl failed"
+.Nm
+relies on
+.Xr cam 4
+to retrieve data from devices and will display this message if the
+device does not have a passthrough driver.
+This can happen, for
+example, if the system uses the
+.Xr nvd 4
+NVMe driver instead of the
+.Xr nda 4
+driver.
+.El
+.Sh SEE ALSO
+.Xr libxo 3 ,
+.Xr cam 4 ,
+.Xr nda 4 ,
+.Xr nvd 4
+.Sh AUTHORS
+This
+utility was written by
+.An Chuck Tuffli Aq Mt chuck@FreeBSD.org .
+.Sh BUGS
+Probably.
diff --git a/contrib/smart/smart.c b/contrib/smart/smart.c
new file mode 100644
index 000000000000..de813e512edf
--- /dev/null
+++ b/contrib/smart/smart.c
@@ -0,0 +1,334 @@
+/*
+ * Copyright (c) 2016-2026 Chuck Tuffli <chuck@tuffli.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <stdbool.h>
+#include <string.h>
+#ifdef LIBXO
+#include <libxo/xo.h>
+#endif
+
+#include "libsmart.h"
+
+#define SMART_NAME "smart"
+#define SMART_VERSION "1.0.3"
+
+extern bool do_debug;
+
+static const char *pn;
+bool do_debug = false;
+static int debugset = 0;
+
+static struct option opts[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "threshold", no_argument, NULL, 't' },
+ { "hex", no_argument, NULL, 'x' },
+ { "attribute", required_argument, NULL, 'a' },
+ { "info", no_argument, NULL, 'i' },
+ { "version", no_argument, NULL, 'v' },
+ { "decode", no_argument, NULL, 'd' },
+ { "no-decode", no_argument, NULL, 'D' },
+ { "debug", no_argument, &debugset, 1 },
+ { NULL, 0, NULL, 0 }
+};
+
+static void
+usage(const char *name)
+{
+ printf("Usage: %s [-htxi] [-a attribute[,attribute]...] <device name>\n", name);
+ printf("\t-h, --help\n");
+ printf("\t-t, --threshold : also print out the threshold values\n");
+ printf("\t-x, --hex : print the values out in hexadecimal\n");
+ printf("\t-a, --attribute : print specified attribute(s)\n");
+ printf("\t-i, --info : print general device information\n");
+ printf("\t-d, --decode: decode the attribute IDs\n");
+ printf("\t-D, --no-decode: don't decode the attribute IDs\n");
+ printf("\t-v, --version : print the version and copyright\n");
+ printf("\t --debug : output diagnostic information\n");
+}
+
+/*
+ * Convert string to an integer
+ *
+ * Returns -1 on error, converted value otherwise
+ */
+static int32_t
+get_val(char *attr, char **next)
+{
+ char *sep = NULL;
+ long val;
+
+ *next = NULL;
+
+ val = strtol(attr, &sep, 0);
+ if ((val == 0) && (errno != 0)) {
+ printf("Error parsing attribute %s", attr);
+ switch (errno) {
+ case EINVAL:
+ printf(" (not a number?)\n");
+ break;
+ case ERANGE:
+ printf(" (value out of range)\n");
+ break;
+ default:
+ printf("\n");
+ }
+ return -1;
+ }
+
+ if (val > INT32_MAX) {
+ printf("Attribute value %ld too big\n", val);
+ return -1;
+ }
+
+ *next = sep;
+ return ((int32_t)val);
+}
+
+/*
+ * Create a match specification from the given attribute
+ *
+ * Attribute format is
+ * <Page ID>:<Attribute ID>
+ * where page and attribute IDs are integers. If the page ID is missing,
+ * match the specified attribute ID on any page (i.e. -1). Valid forms are
+ * <int>:<int>
+ * :<int>
+ * <int>
+ *
+ * Returns 0 on success
+ */
+static int
+add_match(smart_matches_t **matches, char *attr)
+{
+ char *next;
+ int32_t page = -1, id;
+ uint32_t count = 0;
+
+ id = get_val(attr, &next);
+ if (id < 0)
+ return id;
+
+ if (*next == ':') {
+ page = id;
+ id = get_val(next + 1, &next);
+ if (id < 0)
+ return id;
+ }
+
+ if (*matches == NULL) {
+ *matches = calloc(1, sizeof(smart_matches_t) + sizeof(smart_match_t));
+ if (*matches == NULL)
+ return ENOMEM;
+ } else {
+ void *tmp;
+
+ count = (*matches)->count;
+ tmp = realloc(*matches, sizeof(smart_matches_t) + ((count + 1) * sizeof(smart_match_t)));
+ if (tmp == NULL)
+ return ENOMEM;
+ *matches = tmp;
+ }
+
+ (*matches)->m[count].page = page;
+ (*matches)->m[count].id = id;
+ (*matches)->count++;
+ return 0;
+}
+
+/*
+ * Parse the comma separated list of attributes to match
+ *
+ * Caller frees memory allocated for the smart_matches_t pointer.
+ *
+ * Returns 0 on success
+ */
+static int
+parse_matches(smart_matches_t **matches, char *attr)
+{
+ int res;
+
+ if (attr[0] == '\0')
+ return -1;
+
+ while (*attr != '\0') {
+ char *next;
+ size_t len;
+
+ if ((next = strchr(attr, ',')) == NULL) {
+ len = strlen(attr);
+ next = attr + len;
+ } else {
+ len = next - attr;
+ next++;
+ }
+
+ if (len == 0) {
+ printf("Malformed attribute %s\n", attr);
+ return -1;
+ }
+
+ res = add_match(matches, attr);
+ if (res)
+ return res;
+
+ attr = next;
+ }
+
+ return 0;
+}
+
+int
+main(int argc, char *argv[])
+{
+ smart_h h;
+ smart_map_t *sm = NULL;
+ char *devname = NULL;
+ int ch;
+ bool do_thresh = false, do_hex = false, do_info = false, do_version = false,
+ do_descr;
+ smart_matches_t *matches = NULL;
+ int rc = EXIT_SUCCESS;
+
+ /*
+ * By default, keep the original behavior (output numbers only) if
+ * invoked as smart. Otherwise, default to printing the human-friendly
+ * text descriptions.
+ */
+ pn = getprogname();
+ if (strcmp(pn, SMART_NAME) == 0)
+ do_descr = false;
+ else
+ do_descr = true;
+
+#ifdef LIBXO
+ argc = xo_parse_args(argc, argv);
+#endif
+
+ while ((ch = getopt_long(argc, argv, "htxa:idDv", opts, NULL)) != -1) {
+ switch (ch) {
+ case 'h':
+ usage(pn);
+#ifdef LIBXO
+ xo_finish();
+#endif
+ return EXIT_SUCCESS;
+ break;
+ case 't':
+ do_thresh = true;
+ break;
+ case 'x':
+ do_hex = true;
+ break;
+ case 'a':
+ if (parse_matches(&matches, optarg)) {
+ usage(pn);
+ return EXIT_FAILURE;
+ }
+ break;
+ case 'i':
+ do_info = true;
+ break;
+ case 'd':
+ do_descr = true;
+ break;
+ case 'D':
+ do_descr = false;
+ break;
+ case 'v':
+ do_version = true;
+ break;
+ case 0:
+ if (debugset)
+ do_debug = true;
+ break;
+ default:
+ usage(pn);
+#ifdef LIBXO
+ xo_finish();
+#endif
+ return EXIT_FAILURE;
+ }
+ }
+
+ if (do_version) {
+ printf("%s, version %s\n", pn, SMART_VERSION);
+ printf("Copyright (c) 2016-2026 Chuck Tuffli\n"
+ "This is free software; see the source for copying conditions.\n");
+ return EXIT_SUCCESS;
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ devname = argv[0];
+
+ if (!devname) {
+ printf("no device specified\n");
+ usage(pn);
+#ifdef LIBXO
+ xo_finish();
+#endif
+ return EXIT_FAILURE;
+ }
+
+ h = smart_open(SMART_PROTO_AUTO, argv[0]);
+
+ if (h == NULL) {
+ printf("device open failed %s\n", argv[0]);
+#ifdef LIBXO
+ xo_finish();
+#endif
+ return EXIT_FAILURE;
+ }
+
+#ifdef LIBXO
+ xo_open_container("drive");
+#endif
+
+ if (do_info) {
+ smart_print_device_info(h);
+ }
+
+ if (smart_supported(h)) {
+ sm = smart_read(h);
+
+ if (sm) {
+ uint32_t flags = 0;
+
+ if (do_hex)
+ flags |= SMART_OPEN_F_HEX;
+ if (do_thresh)
+ flags |= SMART_OPEN_F_THRESH;
+ if (do_descr)
+ flags |= SMART_OPEN_F_DESCR;
+
+ smart_print(h, sm, matches, flags);
+
+ smart_free(sm);
+ }
+ } else {
+ rc = EXIT_FAILURE;
+ }
+#ifdef LIBXO
+ xo_finish();
+#endif
+ smart_close(h);
+
+ return rc;
+}
diff --git a/etc/mtree/BSD.root.dist b/etc/mtree/BSD.root.dist
index d5ef29c51a92..274397769cac 100644
--- a/etc/mtree/BSD.root.dist
+++ b/etc/mtree/BSD.root.dist
@@ -105,7 +105,7 @@
untrusted tags=package=caroot
..
..
- sysctl.kld.d tags=package=runtime
+ sysctl.kld.d tags=package=rc
..
syslog.d tags=package=syslogd
..
diff --git a/include/unistd.h b/include/unistd.h
index 797eac4c364d..290bcce6a0b3 100644
--- a/include/unistd.h
+++ b/include/unistd.h
@@ -518,6 +518,7 @@ int execvpe(const char *, char * const *, char * const *);
int feature_present(const char *);
int fchroot(int);
char *fflagstostr(u_long);
+ssize_t freadlink(int fd, char *buf, size_t bufsize);
int getdomainname(char *, int);
int getentropy(void *, size_t);
int getgrouplist(const char *, gid_t, gid_t *, int *);
diff --git a/lib/geom/part/gpart.8 b/lib/geom/part/gpart.8
index 32a247529dfe..89bfc3be6f8a 100644
--- a/lib/geom/part/gpart.8
+++ b/lib/geom/part/gpart.8
@@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd April 20, 2026
+.Dd May 9, 2026
.Dt GPART 8
.Os
.Sh NAME
@@ -1527,7 +1527,7 @@ zvol will show up as a GEOM provider only if its
.Sy volmode
is set properly
.Po refer to
-.Xr zfsprops 8
+.Xr zfsprops 7
for details
.Pc .
.El
diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc
index c31f789fd1d1..18a68902f50a 100644
--- a/lib/libc/gen/Makefile.inc
+++ b/lib/libc/gen/Makefile.inc
@@ -56,6 +56,7 @@ SRCS+= \
fmtmsg.c \
fnmatch.c \
fpclassify.c \
+ freadlink.c \
frexp.c \
fstab.c \
ftok.c \
diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map
index 60f34b3a1923..4d22251f7ec5 100644
--- a/lib/libc/gen/Symbol.map
+++ b/lib/libc/gen/Symbol.map
@@ -475,6 +475,7 @@ FBSD_1.8 {
};
FBSD_1.9 {
+ freadlink;
posix_spawn_file_actions_addchdir;
posix_spawn_file_actions_addfchdir;
posix_spawnattr_getexecfd_np;
diff --git a/lib/libc/gen/freadlink.c b/lib/libc/gen/freadlink.c
new file mode 100644
index 000000000000..e1ed7aba6c06
--- /dev/null
+++ b/lib/libc/gen/freadlink.c
@@ -0,0 +1,16 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright 2026 The FreeBSD Foundation
+ *
+ * This software were developed by Konstantin Belousov <kib@FreeBSD.org>
+ * under sponsorship from the FreeBSD Foundation.
+ */
+
+#include <unistd.h>
+
+ssize_t
+freadlink(int fd, char *buf, size_t bufsize)
+{
+ return (readlinkat(fd, "", buf, bufsize));
+}
diff --git a/lib/libc/gen/posix_spawn.c b/lib/libc/gen/posix_spawn.c
index 11cdb5a29d03..faddb0d1494f 100644
--- a/lib/libc/gen/posix_spawn.c
+++ b/lib/libc/gen/posix_spawn.c
@@ -424,7 +424,7 @@ posix_spawn_file_actions_init(posix_spawn_file_actions_t *ret)
fa = malloc(sizeof(struct __posix_spawn_file_actions));
if (fa == NULL)
- return (-1);
+ return (errno);
STAILQ_INIT(&fa->fa_list);
*ret = fa;
diff --git a/lib/msun/Makefile b/lib/msun/Makefile
index a9b07babc0a6..5e9adb533760 100644
--- a/lib/msun/Makefile
+++ b/lib/msun/Makefile
@@ -88,7 +88,7 @@ COMMON_SRCS= b_tgamma.c \
s_lround.c s_lroundf.c s_lroundl.c s_modff.c \
s_nan.c s_nearbyint.c s_nextafter.c s_nextafterf.c \
s_nexttowardf.c s_remquo.c s_remquof.c \
- s_rint.c s_rintf.c s_round.c s_roundf.c \
+ s_rint.c s_rintf.c s_round.c s_roundf.c s_rsqrt.c s_rsqrtf.c \
s_scalbln.c s_scalbn.c s_scalbnf.c s_signbit.c \
s_signgam.c s_significand.c s_significandf.c s_sin.c \
s_sincos.c s_sincosf.c s_sinf.c \
@@ -143,7 +143,7 @@ COMMON_SRCS+= b_tgammal.c catrigl.c \
s_fminimum_numl.c s_fminimum_mag_numl.c \
s_frexpl.c s_logbl.c s_logl.c s_nanl.c \
s_nextafterl.c s_nexttoward.c s_remquol.c s_rintl.c s_roundl.c \
- s_scalbnl.c s_sinl.c s_sincosl.c s_sinpil.c \
+ s_scalbnl.c s_sinl.c s_sincosl.c s_sinpil.c s_rsqrtl.c \
s_tanhl.c s_tanl.c s_tanpil.c s_truncl.c w_cabsl.c
# Work around this warning from gcc:
# lib/msun/ld80/e_powl.c:275:1: error: floating constant exceeds range of
@@ -289,7 +289,7 @@ MLINKS+=sincos.3 sincosf.3 sin.3 sincosl.3
MLINKS+=sinh.3 sinhf.3 sinh.3 sinhl.3
MLINKS+=sinpi.3 sinpif.3 sinpi.3 sinpil.3
MLINKS+=sqrt.3 cbrt.3 sqrt.3 cbrtf.3 sqrt.3 cbrtl.3 sqrt.3 sqrtf.3 \
- sqrt.3 sqrtl.3
+ sqrt.3 sqrtl.3 sqrt.3 rsqrt.3 sqrt.3 rsqrtf.3 sqrt.3 rsqrtl.3
MLINKS+=tan.3 tanf.3 tan.3 tanl.3
MLINKS+=tanh.3 tanhf.3 tanh.3 tanhl.3
MLINKS+=tanpi.3 tanpif.3 tanpi.3 tanpil.3
diff --git a/lib/msun/Symbol.map b/lib/msun/Symbol.map
index 00222c960f80..2484cc13013b 100644
--- a/lib/msun/Symbol.map
+++ b/lib/msun/Symbol.map
@@ -344,4 +344,7 @@ FBSD_1.9 {
fminimum_mag_num;
fminimum_mag_numf;
fminimum_mag_numl;
+ rsqrt;
+ rsqrtf;
+ rsqrtl;
};
diff --git a/lib/msun/man/sqrt.3 b/lib/msun/man/sqrt.3
index f4a217353af0..6da6407ecc4b 100644
--- a/lib/msun/man/sqrt.3
+++ b/lib/msun/man/sqrt.3
@@ -25,17 +25,20 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd February 15, 2020
+.Dd May 7, 2026
.Dt SQRT 3
.Os
.Sh NAME
.Nm cbrt ,
.Nm cbrtf ,
.Nm cbrtl ,
+.Nm rsqrt ,
+.Nm rsqrtf ,
+.Nm rsqrtl,
.Nm sqrt ,
.Nm sqrtf ,
.Nm sqrtl
-.Nd cube root and square root functions
+.Nd cube root, square root, and inverse square root functions
.Sh LIBRARY
.Lb libm
.Sh SYNOPSIS
@@ -47,6 +50,12 @@
.Ft long double
.Fn cbrtl "long double x"
.Ft double
+.Fn rsqrt "double x"
+.Ft float
+.Fn rsqrtf "float x"
+.Ft long double
+.Fn rsqrtl "long double x"
+.Ft double
.Fn sqrt "double x"
.Ft float
.Fn sqrtf "float x"
@@ -63,6 +72,15 @@ the cube root of
.Fa x .
.Pp
The
+.Fn rsqrt ,
+.Fn rsqrtf ,
+and
+.Fn rsqrtl
+functions compute
+the inverse square root of
+.Fa x .
+.Pp
+The
.Fn sqrt ,
.Fn sqrtf ,
and
@@ -77,6 +95,23 @@ The
and
.Fn cbrtl
functions return the requested cube root.
+.Pp
+The
+.Fn rsqrt ,
+.Fn rsqrtf ,
+and
+.Fn rsqrtl
+functions return 1 divided by the square root of
+.Fa x
+unless an error occurs.
+An attempt to take the
+.Fn rsqrt
+of negative
+.Fa x
+raises an invalid exception and causes an \*(Na to be returned.
+The inverse square root of \*(Pm0 returns \*(Pm\(if and
+raises a divide-by-zero exception.
+.Pp
The
.Fn sqrt ,
.Fn sqrtf ,
@@ -104,6 +139,13 @@ and
.Fn sqrtl
functions conform to
.St -isoC-99 .
+The
+.Fn rsqrt ,
+.Fn rsqrtf ,
+and
+.Fn rsqrtl
+functions conform to ISO/IEC 9899:2024 ("ISO C23").
+.\" .St -isoC-24 .
.Sh HISTORY
The
.Fn cbrt
@@ -120,3 +162,10 @@ The
.Fn cbrtl
function appeared in
.Fx 9.0 .
+The
+.Fn rsqrt ,
+.Fn rsqrtf ,
+and
+.Fn rsqrtl
+functions appeared in
+.Fx 16.0 .
diff --git a/lib/msun/src/math.h b/lib/msun/src/math.h
index 9894401160d4..e5c2ccb786a4 100644
--- a/lib/msun/src/math.h
+++ b/lib/msun/src/math.h
@@ -544,6 +544,9 @@ long double fminimum_mag_numl(long double, long double);
double fminimum_num(double, double);
float fminimum_numf(float, float);
long double fminimum_numl(long double, long double);
+double rsqrt(double);
+float rsqrtf(float);
+long double rsqrtl(long double);
#endif /* __ISO_C_VISIBLE >= 2023 */
__END_DECLS
diff --git a/lib/msun/src/math_private.h b/lib/msun/src/math_private.h
index fbd84e246ca7..e9055a9a8c61 100644
--- a/lib/msun/src/math_private.h
+++ b/lib/msun/src/math_private.h
@@ -472,6 +472,89 @@ do { \
} while (0)
/*
+ * Split x into high and low bits where CC is 0x1p(N/2) + 1 where
+ * N is rounded up for types with odd precisions.
+ *
+ * #define _CC (0x1p12F + 1) // float
+ * #define _CC (0x1p27 + 1) // double
+ * #define _CC (0x1p32L + 1) // long double (LD80)
+ * #define _CC (0x1p57L + 1) // long double (LD128)
+ */
+#define _SPLIT(x, xh, xl) \
+do { \
+ typeof(x) __t1; \
+ __t1 = (x) * _CC; \
+ xh = __t1 + ((x) - __t1); \
+ xl = (x) - xh; \
+} while(0)
+
+/*
+ * FAST2SUM requires |x| >= |y|. x and y are full precision.
+ * Note, _2SUMF(x,y) above destroys x and y.
+ */
+#define _FAST2SUM(x, y, hi, lo) \
+do { \
+ hi = (x) + (y); \
+ lo = (y) - (hi - (x)); \
+} while(0)
+
+/*
+ * SLOW2SUM does not require |x| >= |y|. Here, x and y are full precision.
+ * The t1 temporary variable is volatile to prevent compiler optimizations.
+ * Note, _2SUM(x,y) above destroys x and y.
+ */
+#define _SLOW2SUM(x, y, hi, lo) \
+do { \
+ volatile typeof(x) __t1; \
+ typeof(x) __t2; \
+ hi = (x) + (y); \
+ __t1 = hi - (y); \
+ __t2 = hi - __t1; \
+ lo = ((x) - __t1) + ((y) - __t2); \
+} while(0)
+
+/*
+ * x and y are full precision quantities that have been split into high
+ * and low parts via the _SPLIT macro. x and y are added to give z as
+ * high and low parts.
+ */
+#define _XADD(xh, xl, yh, yl, zh, zl) \
+do { \
+ typeof(xh) __s1, __s2, __s3, __s4, __s5, __s6; \
+ _SLOW2SUM(xh, yh, __s1, __s2); \
+ _SLOW2SUM(xl, yl, __s3, __s4); \
+ _FAST2SUM(__s1, __s2 + __s3, __s5, __s6); \
+ _FAST2SUM(__s5, __s6 + __s4, zh, zl); \
+} while(0)
+
+/*
+ * x and y are full precision quantities. r1 and r2 are full precision
+ * high and low parts of the multiplication x * y.
+ */
+#define _MUL(x, y, r1 ,r2) \
+do { \
+ typeof(x) __xh, __xl, __yh, __yl; \
+ typeof(x) __t1; \
+ _SPLIT(x, __xh, __xl); \
+ _SPLIT(y, __yh, __yl); \
+ r1 = (x) * (y); \
+ __t1 = __xh * __yl + (__xh * __yh - r1); \
+ r2 = __xl * __yl + (__xl * __yh + __t1); \
+} while(0)
+
+/*
+ * x and y are full precision quantities that have been split into high
+ * and low parts via the _SPLIT macro. x and y are multiplied to give z
+ * as high and low parts.
+ */
+#define _XMUL(xh, xl, yh, yl, ph, pl) \
+do { \
+ _MUL(xh, yh, ph, pl); \
+ pl += xl * yl + xl * yh + xh * yl; \
+} while(0)
+
+
+/*
* Common routine to process the arguments to nan(), nanf(), and nanl().
*/
void _scan_nan(uint32_t *__words, int __num_words, const char *__s);
diff --git a/lib/msun/src/s_rsqrt.c b/lib/msun/src/s_rsqrt.c
new file mode 100644
index 000000000000..0a513afe8ed2
--- /dev/null
+++ b/lib/msun/src/s_rsqrt.c
@@ -0,0 +1,153 @@
+/*-
+ * Copyright (c) 2026 Steven G. Kargl
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * Compute the inverse sqrt of x, i.e., rsqrt(x) = 1 / sqrt(x).
+ *
+ * First, filter out special cases:
+ *
+ * 1. rsqrt(+-0) = +-inf, and raise FE_DIVBYZERO exception.
+ * 2. rsqrt(nan) = NaN.
+ * 3. rsqrt(+inf) returns +0.
+ * 2. rsqrt(x<0) = NaN, and raises FE_INVALID.
+ *
+ * If x is a subnormal, scale x into the normal range by x*0x1pN; while
+ * recording the exponent of the scale factor N. Split the possibly
+ * scaled x into f*2^n with f in [0.5,1). Set m=n or m=n-N (subnormal).
+ * If n is odd, then set f = f/2 and increase n to n+1. Thus, f is
+ * in [0.25,1) with n even.
+ *
+ * An initial estimate of y = rqrt[f](x) is 1 / sqrt[f](x). Exhaustive
+ * testing of rsqrtf() gave a max ULP of 1.49; while testing 500M x in
+ * [0,1000] gave a max ULP of 1.24 for rsqrt(). The value of y is then
+ * used with one iteration of Goldschmidt's algorithm:
+ *
+ * z = x * y
+ * h = y / 2
+ * r = 0.5 - h * z
+ * y = h * r + h
+ *
+ * A factor of 2 appears missing in the above, but it is included in the
+ * exponent m.
+ */
+#include <fenv.h>
+#include <float.h>
+#include "math.h"
+#include "math_private.h"
+
+#pragma STDC FENV_ACCESS ON
+
+#ifdef _CC
+#undef _CC
+#endif
+#define _CC (0x1p27 + 1)
+
+double
+rsqrt(double x)
+{
+ volatile static const double vzero = 0;
+ static const double half = 0.5;
+ int hx, m, rnd;
+ uint32_t lx, ux;
+ double h, ph, pl, rh, rl, y, zh, zl;
+
+ EXTRACT_WORDS(hx, lx, x);
+ ux = (uint32_t)hx & 0x7fffffff;
+
+ /* x = +-0. Raise exception. */
+ if ((ux | lx) == 0)
+ return (1 / x);
+
+ /* x is NaN. */
+ if (ux > 0x7ff00000)
+ return (x + x);
+
+ /* x is +-inf. */
+ if (ux == 0x7ff00000)
+ return (hx & 0x80000000 ? vzero / vzero : 0.);
+
+ /* x < 0. Raise exception. */
+ if (hx < 0)
+ return (vzero / vzero);
+
+ /*
+ * If x is subnormal, then scale it into the normal range.
+ * Split x into significand and exponent, x = f * 2^m, with
+ * f in [0.5,1) and m a biased exponent.
+ */
+ m = 0;
+ if (hx < 0x00100000) { /* Subnormal */
+ x *= 0x1p54;
+ GET_HIGH_WORD(hx, x);
+ m = -54;
+ }
+ m += (hx >> 20) - 1022;
+ hx = (hx & 0x000fffff) | 0x3fe00000;
+ SET_HIGH_WORD(x, hx);
+
+ /* m is odd. Put x into [0.25,5) and increase m. */
+ if (m & 1) {
+ x /= 2;
+ m += 1;
+ }
+ m = -(m >> 1); /* Prepare for 2^(-m/2). */
+
+ y = 1 / sqrt(x); /* ~52-bit estimate. */
+
+ h = y / 2;
+
+ /*
+ * For values of x with a representation of 0x1.ffffffffffffepN
+ * with N an odd integer, the computed rsqrt() is not correctly
+ * rounded in round-to-nearest without toggling the rounding mode
+ * to FE_TOWARDZERO. Note, FE_DOWNWARD also works. However,
+ * messing with the rounding mode is expensive, so only do it
+ * when necessary. Example, x = 3.9999999999999991
+ * gives y --> hx = 0x3ff00000, lx = 0x00000001
+ */
+ EXTRACT_WORDS(hx, lx, y);
+ if ((hx & 0x000fffff) == 0 && lx == 1) {
+ rnd = fegetround();
+ fesetround(FE_TOWARDZERO);
+ _MUL(x, y, zh, zl);
+ _XMUL(zh, zl, h, 0, ph, pl);
+ fesetround(rnd);
+ } else {
+ _MUL(x, y, zh, zl);
+ _XMUL(zh, zl, h, 0, ph, pl);
+ }
+
+ _XADD(-ph, -pl, half, 0, rh, rl);
+ y = rh * h + h;
+
+ ux = (m + 1024) << 20;
+ INSERT_WORDS(x, ux, 0);
+ return (y *= x);
+}
+
+#if LDBL_MANT_DIG == 53
+__weak_reference(rsqrt, rsqrtl);
+#endif
diff --git a/lib/msun/src/s_rsqrtf.c b/lib/msun/src/s_rsqrtf.c
new file mode 100644
index 000000000000..b71f7baf5657
--- /dev/null
+++ b/lib/msun/src/s_rsqrtf.c
@@ -0,0 +1,155 @@
+/*-
+ * Copyright (c) 2026 Steven G. Kargl
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * Compute the inverse sqrt of x, i.e., rsqrt(x) = 1 / sqrt(x).
+ *
+ * First, filter out special cases:
+ *
+ * 1. rsqrt(+-0) = +-inf, and raise FE_DIVBYZERO exception.
+ * 2. rsqrt(nan) = NaN.
+ * 3. rsqrt(+inf) returns +0.
+ * 2. rsqrt(x<0) = NaN, and raises FE_INVALID.
+ *
+ * If x is a subnormal, scale x into the normal range by x*0x1pN; while
+ * recording the exponent of the scale factor N. Split the possibly
+ * scaled x into f*2^n with f in [0.5,1). Set m=n or m=n-N (subnormal).
+ * If n is odd, then set f = f/2 and increase n to n+1. Thus, f is
+ * in [0.25,1) with n even.
+ *
+ * An initial estimate of y = rqrt[f](x) is 1 / sqrt[f](x). Exhaustive
+ * testing of rsqrtf() gave a max ULP of 1.49; while testing 500M x in
+ * [0,1000] gave a max ULP of 1.24 for rsqrt(). The value of y is then
+ * used with one iteration of Goldschmidt's algorithm:
+ *
+ * z = x * y
+ * h = y / 2
+ * r = 0.5 - h * z
+ * y = h * r + h
+ *
+ * A factor of 2 appears missing in the above, but it is included in the
+ * exponent m.
+ */
+#include <fenv.h>
+#include <float.h>
+#include "math.h"
+#include "math_private.h"
+
+#pragma STDC FENV_ACCESS ON
+
+#ifdef _CC
+#undef _CC
+#endif
+#define _CC (0x1p12F + 1)
+
+float
+rsqrtf(float x)
+{
+ volatile static const float vzero = 0;
+ static const float half = 0.5;
+ uint32_t ix, ux;
+ int m, rnd;
+ float h, ph, pl, rh, rl, y, zh, zl;
+
+ GET_FLOAT_WORD(ix, x);
+ ux = ix & 0x7fffffff;
+
+ /* x = +-0. Raise exception. */
+ if (ux == 0)
+ return (1 / x);
+
+ /* x is NaN. */
+ if (ux > 0x7f800000)
+ return (x + x);
+
+ /* x is +-inf. */
+ if (ux == 0x7f800000)
+ return (ix & 0x80000000 ? vzero / vzero : 0.F);
+
+ /* x < 0. Raise exception. */
+ if (ix & 0x80000000)
+ return (vzero / vzero);
+
+ /*
+ * If x is subnormal, then scale it into the normal range.
+ * Split x into significand and exponent, x = f * 2^m, with
+ * f in [0.5,1) and m a biased exponent.
+ */
+ m = 0;
+ if (ux < 0x00800000) { /* Subnormal */
+ x *= 0x1p25f;
+ GET_FLOAT_WORD(ix, x);
+ m = -25;
+ }
+ m += (ix >> 23) - 126; /* Unbiased exponent */
+ ix = (ix & 0x007fffff) | 0x3f000000;
+ SET_FLOAT_WORD(x, ix); /* x is in [0.5,1). */
+
+ /* m is odd. Put x into [0.25,5) and increase m. */
+ if (m & 1) {
+ x /= 2;
+ m += 1;
+ }
+ m = -(m >> 1); /* Prepare for 2^(-m/2). */
+
+ /*
+ * Exhaustive testing of rsqrtf(x) = 1 / sqrtf(x) with x in
+ * [0x1p-127,0x1p126] shows the this approximation gives a
+ * 22- to 23-bit estimate of rsqrt(f). This is equivalent to
+ * a max ulp of ~1.49.
+ */
+ y = 1 / sqrtf(x);
+
+ h = y / 2;
+
+ /*
+ * For values of x with a representation of 0x1.fffffcpN with
+ * N an odd integer, the computed rsqrtf() is not correctly
+ * rounded in round-to-nearest without toggling the rounding
+ * mode to FE_TOWARDZERO. Note, FE_DOWNWARD also works.
+ * However, messing with the rounding mode is expensive, so
+ * only do it when necessary. Example, x = 0x1.fffffcp3 gives
+ * y --> 0x3f800001.
+ */
+ GET_FLOAT_WORD(ix, y);
+ if ((ix & 0x000fffff) == 1) {
+ rnd = fegetround();
+ fesetround(FE_TOWARDZERO);
+ _MUL(x, y, zh, zl);
+ _XMUL(zh, zl, h, 0, ph, pl);
+ fesetround(rnd);
+ } else {
+ _MUL(x, y, zh, zl);
+ _XMUL(zh, zl, h, 0, ph, pl);
+ }
+
+ _XADD(-ph, -pl, half, 0, rh, rl);
+ y = h * rh + h;
+
+ ix = (uint32_t)(m + 128) << 23;
+ SET_FLOAT_WORD(x, ix);
+ return (y *= x);
+}
diff --git a/lib/msun/src/s_rsqrtl.c b/lib/msun/src/s_rsqrtl.c
new file mode 100644
index 000000000000..34d5cdc48173
--- /dev/null
+++ b/lib/msun/src/s_rsqrtl.c
@@ -0,0 +1,203 @@
+/*-
+ * Copyright (c) 2026 Steven G. Kargl
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * Compute the inverse sqrt of x, i.e., rsqrt(x) = 1 / sqrt(x).
+ *
+ * First, filter out special cases:
+ *
+ * 1. rsqrt(+-0) = +-inf, and raise FE_DIVBYZERO exception.
+ * 2. rsqrt(nan) = NaN.
+ * 3. rsqrt(+inf) returns +0.
+ * 2. rsqrt(x<0) = NaN, and raises FE_INVALID.
+ *
+ * If x is a subnormal, scale x into the normal range by x*0x1pN; while
+ * recording the exponent of the scale factor N. Split the possibly
+ * scaled x into f*2^n with f in [0.5,1). Set m=n or m=n-N (subnormal).
+ * If n is odd, then set f = f/2 and increase n to n+1. Thus, f is
+ * in [0.25,1) with n even.
+ *
+ * An initial estimate of y = rqrt[f](x) is 1 / sqrt[f](x). Exhaustive
+ * testing of rsqrtf() gave a max ULP of 1.49; while testing 500M x in
+ * [0,1000] gave a max ULP of 1.24 for rsqrt(). The value of y is then
+ * used with one iteration of Goldschmidt's algorithm:
+ *
+ * z = x * y
+ * h = y / 2
+ * r = 0.5 - h * z
+ * y = h * r + h
+ *
+ * A factor of 2 appears missing in the above, but it is included in the
+ * exponent m.
+ */
+#include <fenv.h>
+#include <float.h>
+#include "math.h"
+#include "math_private.h"
+#include "fpmath.h"
+
+#pragma STDC FENV_ACCESS ON
+
+#if LDBL_MANT_DIG == 64
+
+#ifdef _CC
+#undef _CC
+#endif
+#define _CC (0x1p32L + 1)
+
+long double
+rsqrtl(long double x)
+{
+ volatile static const double vzero = 0;
+ static const double half = 0.5;
+ uint32_t ux;
+ int m, rnd;
+ long double h, ph, pl, rh, rl, y, zh, zl;
+ union IEEEl2bits u;
+
+ u.e = x;
+ ux = (u.bits.manl | u.bits.manh);
+
+ /* x = +-0. Raise exception. */
+ if ((u.bits.exp | ux) == 0)
+ return (1 / x);
+
+ /* x is NaN or x is +-inf. */
+ if (u.bits.exp == 0x7fff)
+ return (ux ? (x + x) : (u.bits.sign ? vzero / vzero : 0));
+
+ /* x < 0. Raise exception. */
+ if (u.bits.sign)
+ return (vzero / vzero);
+
+ /*
+ * If x is subnormal, then scale it into the normal range.
+ * Split x into significand and exponent, x = f * 2^m, with
+ * f in [0.5,1) and m a biased exponent.
+ */
+ ENTERI();
+
+ if (u.bits.exp == 0) { /* Subnormal */
+ u.e *= 0x1p512;
+ m = u.bits.exp - 0x41fe;
+ } else {
+ m = u.bits.exp - 0x3ffe;
+ }
+ u.bits.exp = 0x3ffe;
+
+ /* m is odd. Put x into [0.25,5) and increase m. */
+ if (m & 1) {
+ u.e /= 2;
+ m += 1;
+ }
+ m = -(m >> 1); /* Prepare for 2^(-m/2). */
+
+ y = 1 / sqrt((double)u.e); /* ~52-bit estimate. */
+ y -= y * (u.e * y * y - 1) / 2; /* ~63-bit estimate. */
+
+ h = y / 2;
+
+ _MUL(u.e, y, zh, zl);
+ _XMUL(zh, zl, h, 0, ph, pl);
+ _XADD(-ph, -pl, half, 0, rh, rl);
+ y = rh * h + h;
+
+ u.e = 1;
+ u.xbits.expsign = 0x3fff + m + 1;
+ RETURNI(y * u.e);
+}
+
+#else
+
+#ifdef _CC
+#undef _CC
+#endif
+#define _CC (0x1p57L + 1)
+
+long double
+rsqrtl(long double x)
+{
+ volatile static const double vzero = 0;
+ int hx, m, rnd;
+ long double y;
+
+ /* x = +-0. Raise exception. */
+ if (x == 0)
+ return (1 / x);
+
+ /* x is NaN. */
+ if (isnan(x))
+ return (x + x);
+
+ /* x is +-inf. */
+ if (isinf(x))
+ return (x > 0 ? 0 : vzero / vzero);
+
+ /* x < 0. Raise exception. */
+ if (x < 0)
+ return (vzero / vzero);
+
+ /*
+ * If x is subnormal, then scale it into the normal range.
+ * Split x into significand and exponent, x = f * 2^m, with
+ * f in [0.5,1) and m a biased exponent.
+ */
+ m = 0;
+ if (!isnormal(x)) {
+ x *= 0x1p114L;
+ m = -114;
+ }
+ x = frexpl(x, &hx);
+ m += hx;
+
+ /* m is odd. Put x into [0.25,5) and increase m. */
+ if (m & 1) {
+ x /= 2;
+ m += 1;
+ }
+ m = -(m >> 1); /* Prepare for 2^(-m/2). */
+
+ y = 1 / sqrt((double)x); /* ~52-bit estimate. */
+ y -= y * (x * y * y - 1) / 2; /* ~104-bit estimate. */
+
+ static const double half = 0.5;
+ long double h, ph, pl, rh, rl, zh, zl;
+
+ h = y / 2;
+
+ rnd = fegetround();
+ fesetround(FE_TOWARDZERO);
+ _MUL(x, y, zh, zl);
+ _XMUL(zh, zl, -h, 0, ph, pl);
+ fesetround(rnd);
+
+ _XADD(ph, pl, half, 0, rh, rl);
+ y = rh * h + h;
+ m++;
+
+ RETURNI(ldexpl(y, m));
+}
+#endif
diff --git a/libexec/nuageinit/nuage.lua b/libexec/nuageinit/nuage.lua
index 2d962b540b23..f3c23a7c3eb8 100644
--- a/libexec/nuageinit/nuage.lua
+++ b/libexec/nuageinit/nuage.lua
@@ -52,6 +52,10 @@ local function decode_base64(input)
return table.concat(result)
end
+local function shell_escape(s)
+ return "'" .. string.gsub(s, "'", "'\\''") .. "'"
+end
+
local function warnmsg(str, prepend)
if not str then
return
@@ -121,7 +125,7 @@ local function sethostname(hostname)
warnmsg("Impossible to open " .. hostnamepath .. ":" .. err)
return
end
- f:write('hostname="' .. hostname .. '"\n')
+ f:write('hostname="' .. hostname:gsub('"', '\\"') .. '"\n')
f:close()
end
@@ -199,7 +203,7 @@ local function adduser(pwd)
if root then
cmd = cmd .. "-R " .. root .. " "
end
- local f = io.popen(cmd .. " usershow " .. pwd.name .. " -7 2> /dev/null")
+ local f = io.popen(cmd .. " usershow " .. shell_escape(pwd.name) .. " -7 2> /dev/null")
local pwdstr = f:read("*a")
f:close()
if pwdstr:len() ~= 0 then
@@ -220,13 +224,17 @@ local function adduser(pwd)
-- a warning but creates the user anyway.
list = purge_group(list)
if #list > 0 then
- extraargs = " -G " .. table.concat(list, ",")
+ local escaped_list = {}
+ for _, g in ipairs(list) do
+ table.insert(escaped_list, shell_escape(g))
+ end
+ extraargs = " -G " .. table.concat(escaped_list, ",")
end
end
-- pw will automatically create a group named after the username
-- do not add a -g option in this case
if pwd.primary_group and pwd.primary_group ~= pwd.name then
- extraargs = extraargs .. " -g " .. pwd.primary_group
+ extraargs = extraargs .. " -g " .. shell_escape(pwd.primary_group)
end
if not pwd.no_create_home then
extraargs = extraargs .. " -m "
@@ -248,9 +256,9 @@ local function adduser(pwd)
if root then
cmd = cmd .. "-R " .. root .. " "
end
- cmd = cmd .. "useradd -n " .. pwd.name .. " -M 0755 -w none "
- cmd = cmd .. extraargs .. " -c '" .. pwd.gecos
- cmd = cmd .. "' -d '" .. pwd.homedir .. "' -s " .. pwd.shell .. postcmd
+ cmd = cmd .. "useradd -n " .. shell_escape(pwd.name) .. " -M 0755 -w none "
+ cmd = cmd .. extraargs .. " -c " .. shell_escape(pwd.gecos)
+ cmd = cmd .. " -d " .. shell_escape(pwd.homedir) .. " -s " .. shell_escape(pwd.shell) .. postcmd
f = io.popen(cmd, "w")
if input then
@@ -267,7 +275,7 @@ local function adduser(pwd)
if root then
cmd = cmd .. "-R " .. root .. " "
end
- cmd = cmd .. "lock " .. pwd.name
+ cmd = cmd .. "lock " .. shell_escape(pwd.name)
os.execute(cmd)
end
return pwd.homedir
@@ -283,7 +291,7 @@ local function addgroup(grp)
if root then
cmd = cmd .. "-R " .. root .. " "
end
- local f = io.popen(cmd .. " groupshow " .. grp.name .. " 2> /dev/null")
+ local f = io.popen(cmd .. " groupshow " .. shell_escape(grp.name) .. " 2> /dev/null")
local grpstr = f:read("*a")
f:close()
if grpstr:len() ~= 0 then
@@ -292,13 +300,17 @@ local function addgroup(grp)
local extraargs = ""
if grp.members then
local list = splitlist(grp.members)
- extraargs = " -M " .. table.concat(list, ",")
+ local escaped_list = {}
+ for _, m in ipairs(list) do
+ table.insert(escaped_list, shell_escape(m))
+ end
+ extraargs = " -M " .. table.concat(escaped_list, ",")
end
cmd = "pw "
if root then
cmd = cmd .. "-R " .. root .. " "
end
- cmd = cmd .. "groupadd -n " .. grp.name .. extraargs
+ cmd = cmd .. "groupadd -n " .. shell_escape(grp.name) .. extraargs
local r = os.execute(cmd)
if not r then
warnmsg("fail to add group " .. grp.name)
@@ -484,7 +496,7 @@ local function exec_change_password(user, password, type, expire)
postcmd = " -w random"
end
end
- cmd = cmd .. "usermod " .. user .. postcmd
+ cmd = cmd .. "usermod " .. shell_escape(user) .. postcmd
if expire then
cmd = cmd .. " -p 1"
else
@@ -577,7 +589,7 @@ local function settimezone(timezone)
root = "/"
end
- local f, _, rc = os.execute("tzsetup -s -C " .. root .. " " .. timezone)
+ local f, _, rc = os.execute("tzsetup -s -C " .. shell_escape(root) .. " " .. shell_escape(timezone))
if not f then
warnmsg("Impossible to configure time zone ( rc = " .. rc .. " )")
@@ -600,8 +612,8 @@ local function install_package(package)
if package == nil then
return true
end
- local install_cmd = "pkg install -y " .. package
- local test_cmd = "pkg info -q " .. package
+ local install_cmd = "pkg install -y " .. shell_escape(package)
+ local test_cmd = "pkg info -q " .. shell_escape(package)
if os.getenv("NUAGE_RUN_TESTS") then
print(install_cmd)
print(test_cmd)
@@ -683,6 +695,7 @@ local function addfile(file, defer)
end
local n = {
+ shell_escape = shell_escape,
warn = warnmsg,
err = errmsg,
chmod = chmod,
diff --git a/libexec/nuageinit/nuageinit b/libexec/nuageinit/nuageinit
index a1ebd3f52b25..fc8d9582b9c6 100755
--- a/libexec/nuageinit/nuageinit
+++ b/libexec/nuageinit/nuageinit
@@ -67,7 +67,14 @@ local function open_resolv_conf()
end
local function open_resolvconf_conf()
- return openat("/etc", "resolvconf.conf")
+ local path_dir = root .. "/etc"
+ local path_name = path_dir .. "/resolvconf.conf"
+ nuage.mkdir_p(path_dir)
+ local f, err = io.open(path_name, "a")
+ if not f then
+ nuage.err("unable to open " .. path_name .. ": " .. err)
+ end
+ return f, path_name
end
local function get_ifaces_by_mac()
@@ -271,8 +278,9 @@ local function nameservers(interface, obj)
end
-- Only call resolvconf with interface if interface is provided
+ local resolvconf_command
if interface then
- resolvconf_command = "resolvconf -a " .. interface .. " < " .. resolv_conf
+ resolvconf_command = "resolvconf -a " .. nuage.shell_escape(interface) .. " < " .. resolv_conf
else
resolvconf_command = "resolvconf -u"
end
@@ -738,6 +746,11 @@ local function load_userdata()
return line, obj
end
+-- Clean up stale resolvconf.conf from previous boot
+if citype ~= "postnet" then
+ os.remove(root .. "/etc/resolvconf.conf")
+end
+
if citype == "config-2" then
-- network
config2_network(ni_path)
diff --git a/libexec/nuageinit/tests/Makefile b/libexec/nuageinit/tests/Makefile
index dc8997717b59..fc7765268660 100644
--- a/libexec/nuageinit/tests/Makefile
+++ b/libexec/nuageinit/tests/Makefile
@@ -18,5 +18,9 @@ ${PACKAGE}FILES+= sethostname.lua
${PACKAGE}FILES+= settimezone.lua
${PACKAGE}FILES+= warn.lua
${PACKAGE}FILES+= addfile.lua
+${PACKAGE}FILES+= decode_base64.lua
+${PACKAGE}FILES+= addsudo.lua
+${PACKAGE}FILES+= adddoas.lua
+${PACKAGE}FILES+= update_sshd_config.lua
.include <bsd.test.mk>
diff --git a/libexec/nuageinit/tests/adddoas.lua b/libexec/nuageinit/tests/adddoas.lua
new file mode 100644
index 000000000000..d4bab41ecc3d
--- /dev/null
+++ b/libexec/nuageinit/tests/adddoas.lua
@@ -0,0 +1,64 @@
+#!/usr/libexec/flua
+---
+-- SPDX-License-Identifier: BSD-2-Clause
+--
+-- Copyright (c) 2026 Baptiste Daroussin <bapt@FreeBSD.org>
+
+local n = require("nuage")
+
+local root = os.getenv("NUAGE_FAKE_ROOTDIR")
+if not root then
+ root = ""
+end
+
+local function get_localbase()
+ local f = io.popen("sysctl -in user.localbase 2> /dev/null")
+ local lb = f:read("*l")
+ f:close()
+ if lb == nil or lb:len() == 0 then
+ lb = "/usr/local"
+ end
+ return lb
+end
+
+local function read_doasconf()
+ local path = root .. get_localbase() .. "/etc/doas.conf"
+ local f = io.open(path, "r")
+ if not f then
+ return nil
+ end
+ local content = f:read("*a")
+ f:close()
+ return content
+end
+
+-- test with a single string rule with %u substitution
+n.adddoas({ name = "testuser", doas = "permit persist %u as root" })
+local content = read_doasconf()
+if not content then
+ n.err("doas.conf not created")
+end
+if content ~= "permit persist testuser as root\n" then
+ n.err("unexpected doas.conf content with %u: '" .. content .. "'")
+end
+
+-- remove file for next test
+os.remove(root .. get_localbase() .. "/etc/doas.conf")
+
+-- test with a table of rules
+n.adddoas({
+ name = "testuser",
+ doas = {
+ "deny %u as foobar",
+ "permit persist %u as root cmd whoami"
+ }
+})
+content = read_doasconf()
+if not content then
+ n.err("doas.conf not created for table")
+end
+if content ~= "deny testuser as foobar\npermit persist testuser as root cmd whoami\n" then
+ n.err("unexpected doas.conf content for table: '" .. content .. "'")
+end
+
+os.exit(0)
diff --git a/libexec/nuageinit/tests/addsudo.lua b/libexec/nuageinit/tests/addsudo.lua
new file mode 100644
index 000000000000..7fc5865d83f4
--- /dev/null
+++ b/libexec/nuageinit/tests/addsudo.lua
@@ -0,0 +1,61 @@
+#!/usr/libexec/flua
+---
+-- SPDX-License-Identifier: BSD-2-Clause
+--
+-- Copyright (c) 2026 Baptiste Daroussin <bapt@FreeBSD.org>
+
+local n = require("nuage")
+
+local root = os.getenv("NUAGE_FAKE_ROOTDIR")
+if not root then
+ root = ""
+end
+
+local function get_localbase()
+ local f = io.popen("sysctl -in user.localbase 2> /dev/null")
+ local lb = f:read("*l")
+ f:close()
+ if lb == nil or lb:len() == 0 then
+ lb = "/usr/local"
+ end
+ return lb
+end
+
+local function read_sudoers()
+ local path = root .. get_localbase() .. "/etc/sudoers.d/90-nuageinit-users"
+ local f = io.open(path, "r")
+ if not f then
+ return nil
+ end
+ local content = f:read("*a")
+ f:close()
+ return content
+end
+
+-- test with a single string rule
+n.addsudo({ name = "testuser", sudo = "ALL=(ALL) NOPASSWD:ALL" })
+local content = read_sudoers()
+if not content then
+ n.err("sudoers file not created")
+end
+if content ~= "testuser ALL=(ALL) NOPASSWD:ALL\n" then
+ n.err("unexpected sudoers content for string rule: '" .. content .. "'")
+end
+
+-- remove file for next test
+os.remove(root .. get_localbase() .. "/etc/sudoers.d/90-nuageinit-users")
+
+-- test with a table of rules
+n.addsudo({
+ name = "testuser",
+ sudo = { "ALL=(ALL) NOPASSWD:/usr/sbin/pw", "ALL=(ALL) ALL" }
+})
+content = read_sudoers()
+if not content then
+ n.err("sudoers file not created for table")
+end
+if content ~= "testuser ALL=(ALL) NOPASSWD:/usr/sbin/pw\ntestuser ALL=(ALL) ALL\n" then
+ n.err("unexpected sudoers content for table: '" .. content .. "'")
+end
+
+os.exit(0)
diff --git a/libexec/nuageinit/tests/decode_base64.lua b/libexec/nuageinit/tests/decode_base64.lua
new file mode 100644
index 000000000000..0951d77f0ed7
--- /dev/null
+++ b/libexec/nuageinit/tests/decode_base64.lua
@@ -0,0 +1,61 @@
+#!/usr/libexec/flua
+---
+-- SPDX-License-Identifier: BSD-2-Clause
+--
+-- Copyright (c) 2026 Baptiste Daroussin <bapt@FreeBSD.org>
+
+local n = require("nuage")
+
+-- decode_base64 is not exported, test via addfile
+
+local function test_decode(input, expected)
+ local r, err = n.addfile({
+ content = input,
+ encoding = "base64",
+ path = "/tmp/nuage_test_b64"
+ }, false)
+ if not r then
+ n.err(err)
+ end
+ local root = os.getenv("NUAGE_FAKE_ROOTDIR")
+ if not root then
+ root = ""
+ end
+ local f = assert(io.open(root .. "/tmp/nuage_test_b64", "r"))
+ local str = f:read("*all")
+ f:close()
+ if str ~= expected then
+ n.err("base64 decode failed: expected '" .. expected
+ .. "' got '" .. str .. "'")
+ end
+end
+
+-- empty input
+test_decode("", "")
+
+-- single byte: 'a'
+test_decode("YQ==", "a")
+
+-- two bytes: 'ab'
+test_decode("YWI=", "ab")
+
+-- three bytes: 'abc'
+test_decode("YWJj", "abc")
+
+-- newline in base64
+test_decode("YmxhCg==", "bla\n")
+
+-- spaces should be ignored
+test_decode("Y Q = =", "a")
+
+-- b64 alias
+local r, err = n.addfile({
+ content = "YQ==",
+ encoding = "b64",
+ path = "/tmp/nuage_test_b64_b64"
+}, false)
+if not r then
+ n.err("b64 encoding alias should work: " .. tostring(err))
+end
+
+os.exit(0)
diff --git a/libexec/nuageinit/tests/nuage.sh b/libexec/nuageinit/tests/nuage.sh
index 57d83b62928a..348a8d93ba09 100644
--- a/libexec/nuageinit/tests/nuage.sh
+++ b/libexec/nuageinit/tests/nuage.sh
@@ -14,6 +14,10 @@ atf_test_case adduser
atf_test_case adduser_passwd
atf_test_case addgroup
atf_test_case addfile
+atf_test_case decode_base64
+atf_test_case addsudo
+atf_test_case adddoas
+atf_test_case update_sshd_config
settimezone_body()
{
@@ -90,6 +94,28 @@ addfile_body()
atf_check /usr/libexec/flua $(atf_get_srcdir)/addfile.lua
}
+decode_base64_body()
+{
+ mkdir tmp
+ atf_check /usr/libexec/flua $(atf_get_srcdir)/decode_base64.lua
+}
+
+addsudo_body()
+{
+ atf_check /usr/libexec/flua $(atf_get_srcdir)/addsudo.lua
+}
+
+adddoas_body()
+{
+ atf_check /usr/libexec/flua $(atf_get_srcdir)/adddoas.lua
+}
+
+update_sshd_config_body()
+{
+ mkdir -p etc/ssh
+ atf_check /usr/libexec/flua $(atf_get_srcdir)/update_sshd_config.lua
+}
+
atf_init_test_cases()
{
atf_add_test_case sethostname
@@ -98,4 +124,8 @@ atf_init_test_cases()
atf_add_test_case adduser_passwd
atf_add_test_case addgroup
atf_add_test_case addfile
+ atf_add_test_case decode_base64
+ atf_add_test_case addsudo
+ atf_add_test_case adddoas
+ atf_add_test_case update_sshd_config
}
diff --git a/libexec/nuageinit/tests/nuageinit.sh b/libexec/nuageinit/tests/nuageinit.sh
index 1fd68d5a178e..89207fdf0aca 100644
--- a/libexec/nuageinit/tests/nuageinit.sh
+++ b/libexec/nuageinit/tests/nuageinit.sh
@@ -801,7 +801,7 @@ packages:
- yeah/plop
EOF
chmod 755 "${PWD}"/media/nuageinit/user_data
- atf_check -s exit:0 -o inline:"pkg install -y yeah/plop\npkg info -q yeah/plop\n" /usr/libexec/nuageinit "${PWD}"/media/nuageinit postnet
+ atf_check -s exit:0 -o inline:"pkg install -y 'yeah/plop'\npkg info -q 'yeah/plop'\n" /usr/libexec/nuageinit "${PWD}"/media/nuageinit postnet
cat > media/nuageinit/user_data << 'EOF'
#cloud-config
@@ -809,7 +809,7 @@ packages:
- curl
EOF
chmod 755 "${PWD}"/media/nuageinit/user_data
- atf_check -o inline:"pkg install -y curl\npkg info -q curl\n" /usr/libexec/nuageinit "${PWD}"/media/nuageinit postnet
+ atf_check -o inline:"pkg install -y 'curl'\npkg info -q 'curl'\n" /usr/libexec/nuageinit "${PWD}"/media/nuageinit postnet
cat > media/nuageinit/user_data << 'EOF'
#cloud-config
@@ -818,7 +818,7 @@ packages:
- meh: bla
EOF
chmod 755 "${PWD}"/media/nuageinit/user_data
- atf_check -o inline:"pkg install -y curl\npkg info -q curl\n" -e inline:"nuageinit: Invalid type: table for packages entry number 2\n" /usr/libexec/nuageinit "${PWD}"/media/nuageinit postnet
+ atf_check -o inline:"pkg install -y 'curl'\npkg info -q 'curl'\n" -e inline:"nuageinit: Invalid type: table for packages entry number 2\n" /usr/libexec/nuageinit "${PWD}"/media/nuageinit postnet
}
config2_userdata_update_packages_body()
diff --git a/libexec/nuageinit/tests/update_sshd_config.lua b/libexec/nuageinit/tests/update_sshd_config.lua
new file mode 100644
index 000000000000..ac56c29986ac
--- /dev/null
+++ b/libexec/nuageinit/tests/update_sshd_config.lua
@@ -0,0 +1,73 @@
+#!/usr/libexec/flua
+---
+-- SPDX-License-Identifier: BSD-2-Clause
+--
+-- Copyright (c) 2026 Baptiste Daroussin <bapt@FreeBSD.org>
+
+local n = require("nuage")
+
+local root = os.getenv("NUAGE_FAKE_ROOTDIR")
+if not root then
+ root = ""
+end
+
+local sshd_config = root .. "/etc/ssh/sshd_config"
+
+local function setup(content)
+ local dir = root .. "/etc/ssh"
+ n.mkdir_p(dir)
+ local f = assert(io.open(sshd_config, "w"))
+ f:write(content)
+ f:close()
+end
+
+local function read_config()
+ local f = assert(io.open(sshd_config, "r"))
+ local content = f:read("*a")
+ f:close()
+ return content
+end
+
+-- Key not found: appended
+setup("SomeOtherKey yes\n")
+n.update_sshd_config("PasswordAuthentication", "yes")
+if read_config() ~= "SomeOtherKey yes\nPasswordAuthentication yes\n" then
+ n.err("Key not found: should be appended")
+end
+
+-- Key with same value: no change
+setup("PasswordAuthentication yes\n")
+n.update_sshd_config("PasswordAuthentication", "yes")
+if read_config() ~= "PasswordAuthentication yes\n" then
+ n.err("Same value: should not change")
+end
+
+-- Key with different value: changed
+setup("PasswordAuthentication no\n")
+n.update_sshd_config("PasswordAuthentication", "yes")
+if read_config() ~= "PasswordAuthentication yes\n" then
+ n.err("Different value: should change")
+end
+
+-- Key with comment
+setup("PasswordAuthentication no # keep this\n")
+n.update_sshd_config("PasswordAuthentication", "yes")
+if read_config() ~= "PasswordAuthentication yes\n" then
+ n.err("Comment stripped: '" .. read_config() .. "'")
+end
+
+-- Case insensitive key matching
+setup("passwordauthentication no\n")
+n.update_sshd_config("PasswordAuthentication", "yes")
+if read_config() ~= "PasswordAuthentication yes\n" then
+ n.err("Case insensitive matching failed")
+end
+
+-- Extra spaces
+setup(" PasswordAuthentication no \n")
+n.update_sshd_config("PasswordAuthentication", "yes")
+if read_config() ~= "PasswordAuthentication yes\n" then
+ n.err("Extra spaces handling failed: '" .. read_config() .. "'")
+end
+
+os.exit(0)
diff --git a/packages/Makefile b/packages/Makefile
index 79bdab9f1abd..71a49d6d06ea 100644
--- a/packages/Makefile
+++ b/packages/Makefile
@@ -66,6 +66,7 @@ SUBDIR= blocklist \
resolvconf \
rip \
runtime \
+ smart \
smbutils \
syslogd \
tcpd \
diff --git a/packages/smart/Makefile b/packages/smart/Makefile
new file mode 100644
index 000000000000..2cc04493da57
--- /dev/null
+++ b/packages/smart/Makefile
@@ -0,0 +1,4 @@
+WORLDPACKAGE= smart
+
+.include <bsd.pkg.mk>
+
diff --git a/packages/smart/smart.ucl b/packages/smart/smart.ucl
new file mode 100644
index 000000000000..e861f61a08ab
--- /dev/null
+++ b/packages/smart/smart.ucl
@@ -0,0 +1,30 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2026 Chuck Tuffli <chuck@FreeBSD.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+comment = "SMART monitoring"
+
+desc = <<EOD
+smart(8) allows the user to monitor the various information reported
+by Self-Monitoring, Analysis and Reporting Technology (SMART) present
+on most ATA, SCSI, and NVMe storage media.
+EOD
+
+annotations {
+ set = "optional,optional-jail"
+}
+
diff --git a/sbin/fsck_msdosfs/fat.c b/sbin/fsck_msdosfs/fat.c
index 567bfcd428cb..5ead0b1bf783 100644
--- a/sbin/fsck_msdosfs/fat.c
+++ b/sbin/fsck_msdosfs/fat.c
@@ -927,6 +927,17 @@ readfat(int fs, struct bootblock *boot, struct fat_descriptor **fp)
default:
break;
}
+ /*
+ * In cache mode the header lives in
+ * fat32_cache_allentries[0]. Mark it
+ * dirty so it is flushed to disk (either
+ * on eviction or in writefat()) before
+ * copyfat() copies the primary FAT to
+ * backup copies.
+ */
+ if (fat->use_cache)
+ fat->fat32_cache_allentries[0].dirty =
+ true;
}
}
}
diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c
index e0e1339a1dce..06a1ee937cd7 100644
--- a/sbin/ipfw/ipfw2.c
+++ b/sbin/ipfw/ipfw2.c
@@ -5515,10 +5515,7 @@ read_options:
break;
case TOK_FLOWID:
- if (proto != IPPROTO_IPV6 )
- errx( EX_USAGE, "flow-id filter is active "
- "only for ipv6 protocol\n");
- fill_flow6( (ipfw_insn_u32 *) cmd, *av, cblen);
+ fill_flow6(insntod(cmd, u32), *av, cblen);
av++;
break;
diff --git a/share/man/man4/rge.4 b/share/man/man4/rge.4
index 24c42f9106dc..5e338ebf9c87 100644
--- a/share/man/man4/rge.4
+++ b/share/man/man4/rge.4
@@ -3,7 +3,7 @@
.\"
.\" SPDX-License-Identifier: BSD-2-Clause
.\"
-.Dd April 5, 2026
+.Dd May 11, 2026
.Dt RGE 4
.Os
.Sh NAME
@@ -137,6 +137,8 @@ RealTek RTL8126 (up to 5 Gbps)
RealTek RTL8127 (up to 10 Gbps)
.It
Killer E3000 (up to 2.5 Gbps)
+.It
+Killer E5000 (up to 5 Gbps)
.El
.Sh SYSCTL VARIABLES
The following variables are available as both
diff --git a/share/man/man4/spkr.4 b/share/man/man4/spkr.4
index 64dfee278de4..a2e55035408c 100644
--- a/share/man/man4/spkr.4
+++ b/share/man/man4/spkr.4
@@ -16,16 +16,6 @@ speaker on an
machine running
.Fx .
.Pp
-Only one process may have this device open at any given time;
-.Xr open 2
-and
-.Xr close 2
-are used to lock and relinquish it.
-An attempt to open when
-another process has the device locked will return -1 with an
-.Er EBUSY
-error
-indication.
Writes to the device are interpreted as `play strings' in a
simple ASCII melody notation.
An
@@ -34,6 +24,13 @@ request
for tone generation at arbitrary
frequencies is also supported.
.Pp
+Only one string can be playing at a time.
+Concurrent
+.Xr write 2
+and
+.Xr ioctl 2
+calls from separate threads or processes are serialized per string.
+.Pp
Sound-generation does not monopolize the processor; in fact, the driver
spends most of its time sleeping while the PC hardware is emitting
tones.
@@ -64,18 +61,25 @@ pointer to the first of an array of tone structures and plays them in
continuous sequence; this array must be terminated by a final member with
a zero duration.
.Pp
-The play-string language is modeled on the PLAY statement conventions of
+The play-string language is a dialect of the Music Markup Language
+(MML) used in various computer and gaming systems since the 1970s.
+It is a subset of the MML variant supported by the PLAY statement of
.Tn IBM
-Advanced BASIC 2.0.
-The
+Advanced BASIC 2.0,
+.Tn MS
+BASICA and GW-BASIC,
+as well as the Standard Musical Expression (SMX) supported in
+.Tn MS
+QBasic.
.Li MB ,
.Li MF ,
and
.Li X
-primitives of PLAY are not
-useful in a timesharing environment and are omitted.
+primitives of MML/SMX are not supported.
The `octave-tracking'
-feature and the slur mark are new.
+feature and the slur mark are specific to the
+.Fx
+implementation.
.Pp
There are 84 accessible notes numbered 1-84 in 7 octaves, each running from
C to B, numbered 0-6; the scale is equal-tempered A440 and octave 3 starts
@@ -115,10 +119,11 @@ Thus ``olbc'' will be played as
``olb>c'', and ``olcb'' as ``olc<b''.
Octave locking is disabled for
one letter note following >, < and O[0123456].
-(The octave-locking
-feature is not supported in
+The octave-locking feature is not supported in
.Tn IBM
-BASIC.)
+and
+.Tn MS
+BASIC dialects.
.It Li >
Bump the current octave up one.
.It Li <
@@ -201,9 +206,11 @@ dotted twice, it is held 9/4, and three times would give 27/8.
A note and its sustain dots may also be followed by a slur mark (underscore).
This causes the normal micro-rest after the note to be filled in, slurring it
to the next one.
-(The slur feature is not supported in
+The slur feature is not supported in
.Tn IBM
-BASIC.)
+and
+.Tn MS
+BASIC dialects.
.Pp
Whitespace in play strings is simply skipped and may be used to separate
melody sections.
@@ -214,16 +221,63 @@ speaker device file
.El
.Sh SEE ALSO
.Xr spkrtest 8
+.Pp
+Additional information about MML:
+.Bl -dash -offset indent
+.It
+.Lk https://electronicmusic.fandom.com/wiki/Music_Macro_Language "The Electronic Music Wiki - Music Macro Language"
+.It
+.Rs
+.%T "IBM Personal Computer BASIC manual"
+.%I "IBM Corporation"
+.%D "1982"
+.Re
+.It
+.Rs
+.%T "BASICA manual"
+.%I "Microsoft Corporation"
+.%D "1982"
+.Re
+.It
+.Rs
+.%T "GW-BASIC manual"
+.%I "Microsoft Corporation"
+.%D "1987"
+.Re
+.It
+.Rs
+.%T "QBasic manual"
+.%I "Microsoft Corporation"
+.%D "1991"
+.Re
+.It
+.Rs
+.%A "Eleanor Selfridge-Field"
+.%T "Beyond MIDI: the handbook of musical codes"
+.%I "MIT Press"
+.%D "1997"
+.Re
+.El
.Sh HISTORY
The
.Nm
device appeared in
.Fx 1.0 .
+.Pp
+Prior to
+.Fx 16 ,
+only one file descriptor could hold the device open.
.Sh AUTHORS
-.An Eric S. Raymond Aq Mt esr@snark.thyrsus.com ,
+.An -nosplit
+The
+.Nm
+driver was written by
+.An Eric S. Raymond Aq Mt esr@snark.thyrsus.com in
June 1990
-.Sh PORTED BY
-.An Andrew A. Chernov Aq Mt ache@astral.msk.su
+and ported by
+.An Andrew A. Chernov Aq Mt ache@astral.msk.su .
+Support for concurrent open was added by
+.An Raphael Poss Aq Mt knz@thaumogen.net .
.Sh BUGS
Due to roundoff in the pitch tables and slop in the tone-generation and timer
hardware (neither of which was designed for precision), neither pitch accuracy
diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile
index 29c822c10eb2..fbb981891ce4 100644
--- a/share/man/man9/Makefile
+++ b/share/man/man9/Makefile
@@ -2333,6 +2333,7 @@ MLINKS+=uidinfo.9 uifind.9 \
uidinfo.9 uihold.9
MLINKS+=uio.9 uiomove.9 \
uio.9 uiomove_frombuf.9 \
+ uio.9 uiomove_fromphys.9 \
uio.9 uiomove_nofault.9
MLINKS+=unr.9 alloc_unr.9 \
unr.9 alloc_unrl.9 \
diff --git a/share/man/man9/uio.9 b/share/man/man9/uio.9
index b143eb6e8e62..a7563125a351 100644
--- a/share/man/man9/uio.9
+++ b/share/man/man9/uio.9
@@ -23,13 +23,14 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd October 22, 2025
+.Dd May 7, 2026
.Dt UIO 9
.Os
.Sh NAME
.Nm uio ,
.Nm uiomove ,
.Nm uiomove_frombuf ,
+.Nm uiomove_fromphys ,
.Nm uiomove_nofault
.Nd device driver I/O routines
.Sh SYNOPSIS
@@ -37,25 +38,29 @@
.In sys/uio.h
.Bd -literal
struct uio {
- struct iovec *uio_iov; /* scatter/gather list */
- int uio_iovcnt; /* length of scatter/gather list */
- off_t uio_offset; /* offset in target object */
- ssize_t uio_resid; /* remaining bytes to copy */
- enum uio_seg uio_segflg; /* address space */
- enum uio_rw uio_rw; /* operation */
- struct thread *uio_td; /* owner */
+ struct iovec *uio_iov; /* scatter/gather list */
+ int uio_iovcnt; /* length of scatter/gather list */
+ off_t uio_offset; /* offset in target object */
+ ssize_t uio_resid; /* remaining bytes to process */
+ enum uio_seg uio_segflg; /* address space */
+ enum uio_rw uio_rw; /* operation */
+ struct thread *uio_td; /* owner */
};
.Ed
+.Pp
.Ft int
.Fn uiomove "void *buf" "int howmuch" "struct uio *uiop"
.Ft int
.Fn uiomove_frombuf "void *buf" "int howmuch" "struct uio *uiop"
.Ft int
+.Fn uiomove_fromphys "vm_page_t ma[]" "vm_offset_t offset" "int howmuch" "struct uio *uiop"
+.Ft int
.Fn uiomove_nofault "void *buf" "int howmuch" "struct uio *uiop"
.Sh DESCRIPTION
The functions
.Fn uiomove ,
.Fn uiomove_frombuf ,
+.Fn uiomove_fromphys ,
and
.Fn uiomove_nofault
are used to transfer data between buffers and I/O vectors that might
@@ -152,10 +157,27 @@ When
.Va uio_offset
is greater than or equal to the buffer size, the result is success
with no bytes transferred, effectively signaling EOF.
+.Pp
+The
+.Fn uiomove_fromphys
+function provides a machine-independent way to copy memory
+to and from the physical address space.
+The
+.Fa "ma[]"
+argument is an array of physical pages.
+Every physical page address in the array provides
+a page-sized chunk of the physical space.
+The
+.Fa "offset"
+argument is the offset into the
+.Fa "ma[]"
+array.
+In particular, the offset does not have to lie within the first page.
.Sh RETURN VALUES
On success
.Fn uiomove ,
.Fn uiomove_frombuf ,
+.Fn uiomove_fromphys ,
and
.Fn uiomove_nofault
will return 0; on error they will return an appropriate error code.
@@ -168,7 +190,7 @@ will not work (the buffer pointer is not being advanced in case of a
partial read), it is just here to demonstrate the
.Nm
handling.
-.Bd -literal
+.Bd -literal -offset 2n
/* MIN() can be found there: */
#include <sys/param.h>
@@ -200,7 +222,8 @@ fooread(struct cdev *dev, struct uio *uio, int flag)
}
.Ed
.Sh ERRORS
-.Fn uiomove
+.Fn uiomove ,
+.Fn uiomove_fromphys
and
.Fn uiomove_nofault
will fail and return the following error code if:
@@ -211,7 +234,7 @@ The invoked
or
.Xr copyout 9
returned
-.Er EFAULT
+.Er EFAULT .
.El
.Pp
In addition,
diff --git a/stand/i386/boot2/sio.S b/stand/i386/boot2/sio.S
index de554efb5b3e..5c4650dc0533 100644
--- a/stand/i386/boot2/sio.S
+++ b/stand/i386/boot2/sio.S
@@ -80,3 +80,5 @@ sio_ischar: movw $SIO_PRT+0x5,%dx # Line status register
inb (%dx),%al # Received data
andb $0x1,%al # ready?
ret # To caller
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/sys/amd64/linux/linux_locore.asm b/sys/amd64/linux/linux_locore.asm
index 19a6ac5d50d8..d4af90bda5fb 100644
--- a/sys/amd64/linux/linux_locore.asm
+++ b/sys/amd64/linux/linux_locore.asm
@@ -85,3 +85,5 @@ END(linux_rt_sigcode)
.balign 4
.previous
#endif
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/sys/amd64/linux/linux_support.S b/sys/amd64/linux/linux_support.S
index 7cc59b205a97..2ab46fe8c5ea 100644
--- a/sys/amd64/linux/linux_support.S
+++ b/sys/amd64/linux/linux_support.S
@@ -227,3 +227,5 @@ ENTRY(futex_xorl_smap)
movq %rax,PCB_ONFAULT(%r8)
ret
END(futex_xorl_smap)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/sys/amd64/linux32/linux32_locore.asm b/sys/amd64/linux32/linux32_locore.asm
index 4b77bd32600e..cc4b0488edb0 100644
--- a/sys/amd64/linux32/linux32_locore.asm
+++ b/sys/amd64/linux32/linux32_locore.asm
@@ -128,3 +128,5 @@ END(__kernel_vsyscall)
.balign 4
.previous
#endif
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/sys/amd64/linux32/linux32_support.S b/sys/amd64/linux32/linux32_support.S
index a316a9bf066d..1018b6ce579c 100644
--- a/sys/amd64/linux32/linux32_support.S
+++ b/sys/amd64/linux32/linux32_support.S
@@ -227,3 +227,5 @@ ENTRY(futex_xorl_smap)
movq %rax,PCB_ONFAULT(%r8)
ret
END(futex_xorl_smap)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/sys/arm/include/_types.h b/sys/arm/include/_types.h
index 7319d950443b..9fde5fc5d7c9 100644
--- a/sys/arm/include/_types.h
+++ b/sys/arm/include/_types.h
@@ -57,6 +57,7 @@ typedef __int64_t __int_fast64_t;
typedef __int32_t __register_t;
typedef __int32_t __segsz_t; /* segment size (in pages) */
typedef __int64_t __time_t; /* time()... */
+#define __SIZEOF_TIME_T __SIZEOF_INT64_T
typedef __uint32_t __uint_fast8_t;
typedef __uint32_t __uint_fast16_t;
typedef __uint32_t __uint_fast32_t;
diff --git a/sys/arm64/arm64/busdma_bounce.c b/sys/arm64/arm64/busdma_bounce.c
index 74fa611e6d1a..db7e108812aa 100644
--- a/sys/arm64/arm64/busdma_bounce.c
+++ b/sys/arm64/arm64/busdma_bounce.c
@@ -36,6 +36,7 @@
#include <sys/domainset.h>
#include <sys/malloc.h>
#include <sys/bus.h>
+#include <sys/busdma_bufalloc.h>
#include <sys/interrupt.h>
#include <sys/kernel.h>
#include <sys/ktr.h>
@@ -56,6 +57,7 @@
#include <machine/atomic.h>
#include <machine/bus.h>
#include <machine/md_var.h>
+#include <machine/rsi.h>
#include <arm64/include/bus_dma_impl.h>
#define MAX_BPAGES 4096
@@ -120,6 +122,8 @@ static void _bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map,
static void _bus_dmamap_count_phys(bus_dma_tag_t dmat, bus_dmamap_t map,
vm_paddr_t buf, bus_size_t buflen, int flags);
+static busdma_bufalloc_t nonsecure_allocator;
+
static MALLOC_DEFINE(M_BUSDMA, "busdma", "busdma metadata");
#define dmat_alignment(dmat) ((dmat)->common.alignment)
@@ -215,6 +219,10 @@ might_bounce(bus_dma_tag_t dmat, bus_dmamap_t map, bus_addr_t paddr,
if (map && (map->flags & DMAMAP_FROM_DMAMEM) != 0)
return (false);
+ /* Bounce if accessing secure memory */
+ if (in_realm() && !(paddr & prot_ns_shared_pa))
+ return (true);
+
if ((dmat->bounce_flags & BF_COULD_BOUNCE) != 0)
return (true);
@@ -239,6 +247,10 @@ must_bounce(bus_dma_tag_t dmat, bus_dmamap_t map, bus_addr_t paddr,
addr_needs_bounce(dmat, paddr))
return (true);
+ /* Bounce if accessing secure memory */
+ if (in_realm() && !(paddr & prot_ns_shared_pa))
+ return (true);
+
return (false);
}
@@ -492,6 +504,7 @@ static int
bounce_bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags,
bus_dmamap_t *mapp)
{
+ struct busdma_bufzone *bufzone;
vm_memattr_t attr;
int mflags;
@@ -524,6 +537,9 @@ bounce_bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags,
else
attr = VM_MEMATTR_DEFAULT;
+ if (in_realm())
+ mflags |= M_UNPROTECTED;
+
/*
* Create the map, but don't set the could bounce flag as
* this allocation should never bounce;
@@ -567,13 +583,16 @@ bounce_bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags,
*
* In the meantime warn the user if malloc gets it wrong.
*/
- if (dmat->alloc_size <= PAGE_SIZE &&
+
+ bufzone = busdma_bufalloc_findzone(nonsecure_allocator,
+ dmat->alloc_size);
+
+ if (bufzone &&
+ dmat->alloc_size <= PAGE_SIZE &&
dmat->alloc_alignment <= PAGE_SIZE &&
dmat->common.lowaddr >= ptoa((vm_paddr_t)Maxmem) &&
attr == VM_MEMATTR_DEFAULT) {
- *vaddr = malloc_domainset_aligned(dmat->alloc_size,
- dmat->alloc_alignment, M_DEVBUF,
- DOMAINSET_PREF(dmat->common.domain), mflags);
+ *vaddr = uma_zalloc(bufzone->umazone, mflags);
} else if (dmat->common.nsegments >=
howmany(dmat->alloc_size, MIN(dmat->common.maxsegsz, PAGE_SIZE)) &&
dmat->alloc_alignment <= PAGE_SIZE &&
@@ -1148,3 +1167,44 @@ struct bus_dma_impl bus_dma_bounce_impl = {
.load_kmsan = bounce_bus_dmamap_load_kmsan,
#endif
};
+
+static void *
+nonsecure_alloc(uma_zone_t zone, vm_size_t size, int domain, uint8_t *pflag,
+ int wait)
+{
+ void *p; /* Returned page */
+
+ *pflag = UMA_SLAB_KERNEL;
+ p = kmem_malloc_domainset(DOMAINSET_FIXED(domain), size,
+ wait | M_UNPROTECTED);
+
+ return (p);
+}
+
+static void
+nonsecure_free(void *mem, vm_size_t size, uint8_t flags)
+{
+ KASSERT((flags & UMA_SLAB_KERNEL) != 0,
+ ("UMA: page_free used with invalid flags %x", flags));
+
+ kmem_free(mem, size);
+}
+
+static void
+busdma_bounce_init(void *dummy)
+{
+ if (in_realm())
+ nonsecure_allocator = busdma_bufalloc_create("nonsecure",
+ dcache_line_size, /* minimum_alignment */
+ nonsecure_alloc, /* uma_alloc func */
+ nonsecure_free, /* uma_free func */
+ UMA_ZONE_NOTOUCH); /* uma_zcreate_flags */
+ else
+ nonsecure_allocator = busdma_bufalloc_create("nonsecure",
+ dcache_line_size, /* minimum_alignment */
+ NULL, /* uma_alloc func */
+ NULL, /* uma_free func */
+ UMA_ZONE_NOTOUCH); /* uma_zcreate_flags */
+}
+
+SYSINIT(busdma, SI_SUB_KMEM + 1, SI_ORDER_FIRST, busdma_bounce_init, NULL);
diff --git a/sys/arm64/arm64/efirt_machdep.c b/sys/arm64/arm64/efirt_machdep.c
index b079393cd2a9..07946a2bdb82 100644
--- a/sys/arm64/arm64/efirt_machdep.c
+++ b/sys/arm64/arm64/efirt_machdep.c
@@ -46,6 +46,7 @@
#include <sys/vmmeter.h>
#include <machine/pte.h>
+#include <machine/rsi.h>
#include <machine/vmparam.h>
#include <vm/vm.h>
@@ -171,6 +172,7 @@ efi_create_1t1_map(struct efi_md *map, int ndesc, int descsz)
vm_page_t efi_l0_page;
uint64_t idx;
int i, mode;
+ uint64_t pa;
obj_1t1_pt = vm_pager_allocate(OBJT_PHYS, NULL, L0_ENTRIES +
L0_ENTRIES * Ln_ENTRIES + L0_ENTRIES * Ln_ENTRIES * Ln_ENTRIES +
@@ -231,7 +233,13 @@ efi_create_1t1_map(struct efi_md *map, int ndesc, int descsz)
for (va = p->md_phys, idx = 0; idx < p->md_pages;
idx += (PAGE_SIZE / EFI_PAGE_SIZE), va += PAGE_SIZE) {
l3 = efi_1t1_l3(va);
- *l3 = va | l3_attr;
+
+ if (mode == VM_MEMATTR_DEVICE && in_realm())
+ pa = va | prot_ns_shared_pa;
+ else
+ pa = va;
+
+ *l3 = PHYS_TO_PTE(pa) | l3_attr;
}
VM_OBJECT_WUNLOCK(obj_1t1_pt);
}
diff --git a/sys/arm64/arm64/locore.S b/sys/arm64/arm64/locore.S
index 14300eceb6d5..b200aa93c281 100644
--- a/sys/arm64/arm64/locore.S
+++ b/sys/arm64/arm64/locore.S
@@ -799,7 +799,7 @@ common:
adrp x9, socdev_va
str x17, [x9, :lo12:socdev_va]
- mov x9, #(SOCDEV_PA & ~L2_OFFSET) /* PA start */
+ ldr x9, =(SOCDEV_PA) /* PA start */
mov x10, #1
bl build_l2_block_pagetable
#endif
diff --git a/sys/arm64/arm64/machdep.c b/sys/arm64/arm64/machdep.c
index adfb509d4924..d219c737c215 100644
--- a/sys/arm64/arm64/machdep.c
+++ b/sys/arm64/arm64/machdep.c
@@ -86,6 +86,7 @@
#include <machine/metadata.h>
#include <machine/md_var.h>
#include <machine/pcb.h>
+#include <machine/rsi.h>
#include <machine/undefined.h>
#include <machine/vmparam.h>
@@ -103,6 +104,7 @@
#include <dev/ofw/openfirm.h>
#endif
+#include <dev/psci/psci.h>
#include <dev/smbios/smbios.h>
_Static_assert(sizeof(struct pcb) == 1248, "struct pcb is incorrect size");
@@ -889,6 +891,9 @@ initarm(struct arm64_bootparams *abp)
valid = bus_probe();
+ psci_init(NULL);
+ arm64_rsi_setup_memory();
+
cninit();
set_ttbr0(abp->kern_ttbr0);
pmap_s1_invalidate_all_kernel();
diff --git a/sys/arm64/arm64/pmap.c b/sys/arm64/arm64/pmap.c
index 595fba2da411..adc583812e5b 100644
--- a/sys/arm64/arm64/pmap.c
+++ b/sys/arm64/arm64/pmap.c
@@ -152,6 +152,7 @@
#include <machine/machdep.h>
#include <machine/md_var.h>
#include <machine/pcb.h>
+#include <machine/rsi.h>
#ifdef NUMA
#define PMAP_MEMDOM MAXMEMDOM
@@ -205,6 +206,8 @@ __exclusive_cache_line static struct pmap_large_md_page pv_dummy_large;
#define pv_dummy pv_dummy_large.pv_page
__read_mostly static struct pmap_large_md_page *pv_table;
+__read_mostly uint64_t prot_ns_shared_pa;
+
static struct pmap_large_md_page *
_pa_to_pmdp(vm_paddr_t pa)
{
@@ -537,6 +540,9 @@ static int pmap_bti_copy(pmap_t dst_pmap, pmap_t src_pmap);
static void pmap_bti_deassign_all(pmap_t pmap);
static void pagezero(void *);
+static void pmap_set_protected(pt_entry_t old_l3);
+static void pmap_set_unprotected(pt_entry_t new_l3);
+
/*
* These load the old table data and store the new value.
* They need to be atomic as the System MMU may write to the table at
@@ -2379,6 +2385,11 @@ pmap_kenter(vm_offset_t sva, vm_size_t size, vm_paddr_t pa, int mode)
KASSERT((size & PAGE_MASK) == 0,
("pmap_kenter: Mapping is not page-sized"));
+ /* CCA - Map devices as nonsecure */
+ if (in_realm() && (mode == VM_MEMATTR_DEVICE ||
+ mode == VM_MEMATTR_DEVICE_NP))
+ pa |= prot_ns_shared_pa;
+
attr = ATTR_AF | pmap_sh_attr | ATTR_S1_AP(ATTR_S1_AP_RW) |
ATTR_S1_XN | ATTR_KERN_GP | ATTR_S1_IDX(mode);
old_l3e = 0;
@@ -4222,6 +4233,9 @@ pmap_remove_l3_range(pmap_t pmap, pd_entry_t l2e, vm_offset_t sva,
if ((old_l3 & ATTR_SW_WIRED) != 0)
pmap->pm_stats.wired_count--;
pmap_resident_count_dec(pmap, 1);
+ /* Below will only be true in a realm environment. */
+ if (PTE_TO_PHYS(old_l3) & prot_ns_shared_pa)
+ pmap_set_protected(old_l3);
if ((old_l3 & ATTR_SW_MANAGED) != 0) {
m = PTE_TO_VM_PAGE(old_l3);
if (pmap_pte_dirty(pmap, old_l3))
@@ -5374,6 +5388,28 @@ restart:
return (KERN_SUCCESS);
}
+static void
+pmap_set_unprotected(pt_entry_t new_l3)
+{
+ vm_paddr_t pa;
+
+ pa = PTE_TO_PHYS(new_l3) & ~prot_ns_shared_pa;
+
+ rsi_set_addr_range_state(pa, pa + L3_SIZE, RSI_RIPAS_EMPTY,
+ RSI_CHANGE_DESTROYED, NULL);
+}
+
+static void
+pmap_set_protected(pt_entry_t old_l3)
+{
+ vm_paddr_t pa;
+
+ pa = PTE_TO_PHYS(old_l3) & ~prot_ns_shared_pa;
+
+ rsi_set_addr_range_state(pa, pa + L3_SIZE, RSI_RIPAS_RAM,
+ RSI_CHANGE_DESTROYED, NULL);
+}
+
/*
* Insert the given physical page (p) at
* the specified virtual address (v) in the
@@ -5407,6 +5443,8 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
if ((m->oflags & VPO_UNMANAGED) == 0)
VM_PAGE_OBJECT_BUSY_ASSERT(m);
pa = VM_PAGE_TO_PHYS(m);
+ if (in_realm() && (flags & PMAP_ENTER_UNPROTECTED) != 0)
+ pa |= prot_ns_shared_pa;
new_l3 = (pt_entry_t)(PHYS_TO_PTE(pa) | ATTR_AF | pmap_sh_attr |
L3_PAGE);
new_l3 |= pmap_pte_memattr(pmap, m->md.pv_memattr);
@@ -5726,6 +5764,10 @@ validate:
#endif
rv = KERN_SUCCESS;
+
+ if (in_realm() && (flags & PMAP_ENTER_UNPROTECTED) != 0)
+ pmap_set_unprotected(new_l3);
+
out:
if (lock != NULL)
rw_wunlock(lock);
diff --git a/sys/arm64/arm64/rsi.c b/sys/arm64/arm64/rsi.c
new file mode 100644
index 000000000000..85c7896e13ce
--- /dev/null
+++ b/sys/arm64/arm64/rsi.c
@@ -0,0 +1,185 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2026 Arm Ltd
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "opt_platform.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/physmem.h>
+#include <sys/rwlock.h>
+
+#include <vm/vm_page.h>
+
+#include <machine/rsi.h>
+#include <machine/vmparam.h>
+
+#include <dev/psci/psci.h>
+#include <dev/psci/smccc.h>
+
+static struct realm_config config;
+static bool rsi_present = false;
+
+#define PHYSMAP_SIZE (2 * (VM_PHYSSEG_MAX - 1))
+
+static vm_paddr_t physmap[PHYSMAP_SIZE];
+
+static unsigned long
+rsi_request_version(unsigned long req, unsigned long *out_lower,
+ unsigned long *out_higher)
+{
+ struct arm_smccc_res res;
+
+ arm_smccc_invoke_smc(SMC_RSI_ABI_VERSION, req, &res);
+
+ if (out_lower != NULL)
+ *out_lower = res.a1;
+ if (out_higher != NULL)
+ *out_higher = res.a2;
+
+ return (res.a0);
+}
+
+static inline unsigned long
+rsi_get_realm_config(struct realm_config *cfg)
+{
+ struct arm_smccc_res res;
+
+ arm_smccc_invoke_smc(SMC_RSI_REALM_CONFIG, vtophys(cfg), &res);
+ return (res.a0);
+}
+
+static bool
+rsi_version_matches(void)
+{
+ unsigned long ver_lower, ver_higher;
+ unsigned long ret;
+
+ ret = rsi_request_version(RSI_ABI_VERSION, &ver_lower, &ver_higher);
+
+ if (ret == SMCCC_RET_NOT_SUPPORTED)
+ return (false);
+
+ if (ret != RSI_SUCCESS) {
+ printf("RME: RMM doesn't support RSI version %lu.%lu. Supported range: %lu.%lu-%lu.%lu\n",
+ RSI_ABI_VERSION_MAJOR, RSI_ABI_VERSION_MINOR,
+ RSI_ABI_VERSION_GET_MAJOR(ver_lower),
+ RSI_ABI_VERSION_GET_MINOR(ver_lower),
+ RSI_ABI_VERSION_GET_MAJOR(ver_higher),
+ RSI_ABI_VERSION_GET_MINOR(ver_higher));
+ return (false);
+ }
+
+ printf("RME: Using RSI version %lu.%lu\n",
+ RSI_ABI_VERSION_GET_MAJOR(ver_lower),
+ RSI_ABI_VERSION_GET_MINOR(ver_lower));
+
+ return (true);
+}
+
+
+unsigned long
+rsi_set_addr_range_state(vm_paddr_t start, vm_paddr_t end, enum ripas state,
+ unsigned long flags, vm_paddr_t *top)
+{
+ struct arm_smccc_res res;
+
+ arm_smccc_smc(SMC_RSI_IPA_STATE_SET, start, end, state, flags, 0, 0, 0,
+ &res);
+
+ if (top)
+ *top = res.a1;
+
+ return (res.a0);
+}
+
+static int
+rsi_set_memory_range(vm_paddr_t start, vm_paddr_t end, enum ripas state,
+ unsigned long flags)
+{
+ unsigned long ret;
+ vm_paddr_t top;
+
+ while (start != end) {
+ ret = rsi_set_addr_range_state(start, end, state, flags, &top);
+ if (ret || top < start || top > end)
+ return (-EINVAL);
+ start = top;
+ }
+
+ return (0);
+}
+
+/*
+ * Convert the specified range to RAM. Do not convert any pages that may have
+ * been DESTROYED, without our permission.
+ */
+static int
+rsi_set_memory_range_protected_safe(vm_paddr_t start, vm_paddr_t end)
+{
+ return (rsi_set_memory_range(start, end, RSI_RIPAS_RAM,
+ RSI_NO_CHANGE_DESTROYED));
+}
+
+void
+arm64_rsi_setup_memory(void)
+{
+ int physmap_idx;
+ int i;
+
+ if (!psci_conduit_is_smc())
+ return;
+ if (!rsi_version_matches())
+ return;
+ if (rsi_get_realm_config(&config))
+ return;
+
+ prot_ns_shared_pa = 1ul << (config.ipa_bits - 1);
+ if (bootverbose)
+ printf("arm64_rsi_setup_memory: rsi_present, ipa_bits=%lu prot_ns_shared_pa=%lx\n",
+ config.ipa_bits, prot_ns_shared_pa);
+ rsi_present = true;
+
+ physmap_idx = physmem_all(physmap, nitems(physmap));
+
+ if (bootverbose)
+ printf("physmap:\n");
+
+ for (i = 0; i < physmap_idx; i += 2) {
+ if (bootverbose)
+ printf(" %lx %lx\n", physmap[i], physmap[i + 1]);
+
+ if (rsi_set_memory_range_protected_safe(physmap[i],
+ physmap[i + 1]))
+ panic("rsi_set_memory_range_protected_safe failed");
+ }
+}
+
+bool
+in_realm(void)
+{
+ return (rsi_present);
+}
diff --git a/sys/arm64/include/_types.h b/sys/arm64/include/_types.h
index 98f7dea67520..c46f64b2b252 100644
--- a/sys/arm64/include/_types.h
+++ b/sys/arm64/include/_types.h
@@ -55,6 +55,7 @@ typedef __int64_t __int_fast64_t;
typedef __int64_t __register_t;
typedef __int64_t __segsz_t; /* segment size (in pages) */
typedef __int64_t __time_t; /* time()... */
+#define __SIZEOF_TIME_T __SIZEOF_INT64_T
typedef __uint32_t __uint_fast8_t;
typedef __uint32_t __uint_fast16_t;
typedef __uint32_t __uint_fast32_t;
diff --git a/sys/arm64/include/pmap.h b/sys/arm64/include/pmap.h
index 2ee70fc754da..00b54a874e12 100644
--- a/sys/arm64/include/pmap.h
+++ b/sys/arm64/include/pmap.h
@@ -43,6 +43,7 @@
#ifndef LOCORE
#include <sys/queue.h>
+#include <sys/systm.h>
#include <sys/_lock.h>
#include <sys/_mutex.h>
#include <sys/_pv_entry.h>
@@ -132,6 +133,8 @@ extern vm_offset_t virtual_end;
extern pt_entry_t pmap_sh_attr;
+extern __read_mostly uint64_t prot_ns_shared_pa;
+
/*
* Macros to test if a mapping is mappable with an L1 Section mapping
* or an L2 Large Page mapping.
diff --git a/sys/arm64/include/rsi.h b/sys/arm64/include/rsi.h
new file mode 100644
index 000000000000..82e54f9c57e3
--- /dev/null
+++ b/sys/arm64/include/rsi.h
@@ -0,0 +1,129 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2026 Arm Ltd
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _MACHINE_RSI_H_
+#define _MACHINE_RSI_H_
+
+extern uint64_t prot_ns_shared;
+
+bool in_realm(void);
+
+void arm64_rsi_setup_memory(void);
+
+/*
+ * The major version number of the RSI implementation. This is increased when
+ * the binary format or semantics of the SMC calls change.
+ */
+#define RSI_ABI_VERSION_MAJOR UL(1)
+
+/*
+ * The minor version number of the RSI implementation. This is increased when
+ * a bug is fixed, or a feature is added without breaking binary compatibility.
+ */
+#define RSI_ABI_VERSION_MINOR UL(0)
+
+#define RSI_ABI_VERSION ((RSI_ABI_VERSION_MAJOR << 16) | \
+ RSI_ABI_VERSION_MINOR)
+
+#define RSI_ABI_VERSION_GET_MAJOR(_version) ((_version) >> 16)
+#define RSI_ABI_VERSION_GET_MINOR(_version) ((_version) & 0xFFFF)
+
+#define RSI_SUCCESS UL(0)
+#define RSI_ERROR_INPUT UL(1)
+#define RSI_ERROR_STATE UL(2)
+#define RSI_INCOMPLETE UL(3)
+#define RSI_ERROR_UNKNOWN UL(4)
+
+#define SMC_RSI_FID(n) SMCCC_FUNC_ID(SMCCC_FAST_CALL, \
+ SMCCC_64BIT_CALL, \
+ SMCCC_STD_SECURE_SERVICE_CALLS, \
+ n)
+
+/*
+ * Returns RSI version.
+ *
+ * arg1 == Requested interface revision
+ * ret0 == Status / error
+ * ret1 == Lower implemented interface revision
+ * ret2 == Higher implemented interface revision
+ */
+#define SMC_RSI_ABI_VERSION SMC_RSI_FID(0x190)
+
+/*
+ * Read configuration for the current Realm.
+ *
+ * arg1 == struct realm_config addr
+ * ret0 == Status / error
+ */
+#define SMC_RSI_REALM_CONFIG SMC_RSI_FID(0x196)
+
+struct realm_config {
+ union {
+ struct {
+ unsigned long ipa_bits; /* Width of IPA in bits */
+ unsigned long hash_algo; /* Hash algorithm */
+ };
+ uint8_t pad[0x200];
+ };
+ union {
+ uint8_t rpv[64]; /* Realm Personalization Value */
+ uint8_t pad2[0xe00];
+ };
+ /*
+ * The RMM requires the configuration structure to be aligned to a 4k
+ * boundary, ensure this happens by aligning this structure.
+ */
+} __aligned(0x1000);
+
+/*
+ * Request RIPAS of a target IPA range to be changed to a specified value.
+ *
+ * arg1 == Base IPA address of target region
+ * arg2 == Top of the region
+ * arg3 == RIPAS value
+ * arg4 == flags
+ * ret0 == Status / error
+ * ret1 == Top of modified IPA range
+ * ret2 == Whether the Host accepted or rejected the request
+ */
+#define SMC_RSI_IPA_STATE_SET SMC_RSI_FID(0x197)
+
+#define RSI_NO_CHANGE_DESTROYED UL(0)
+#define RSI_CHANGE_DESTROYED UL(1)
+
+#define RSI_ACCEPT UL(0)
+#define RSI_REJECT UL(1)
+
+enum ripas {
+ RSI_RIPAS_EMPTY = 0,
+ RSI_RIPAS_RAM
+};
+
+unsigned long rsi_set_addr_range_state(vm_paddr_t start, vm_paddr_t end,
+ enum ripas state, unsigned long flags, vm_paddr_t *top);
+
+#endif /* !_MACHINE_RSI_H_ */
diff --git a/sys/arm64/linux/linux_locore.asm b/sys/arm64/linux/linux_locore.asm
index c330546702f1..20846a324647 100644
--- a/sys/arm64/linux/linux_locore.asm
+++ b/sys/arm64/linux/linux_locore.asm
@@ -51,3 +51,5 @@ __user_rt_sigreturn:
mov x8, #LINUX_SYS_linux_rt_sigreturn
svc #0
EEND(__kernel_rt_sigreturn)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/sys/arm64/linux/linux_support.S b/sys/arm64/linux/linux_support.S
index 3b16583e9d54..61a0604dd91b 100644
--- a/sys/arm64/linux/linux_support.S
+++ b/sys/arm64/linux/linux_support.S
@@ -176,3 +176,5 @@ ENTRY(futex_xorl)
END(futex_xorl)
GNU_PROPERTY_AARCH64_FEATURE_1_NOTE(GNU_PROPERTY_AARCH64_FEATURE_1_VAL)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/sys/compat/linux/linux_vdso_inc.S b/sys/compat/linux/linux_vdso_inc.S
index 44cc357b4a4a..d2ac3e28aabe 100644
--- a/sys/compat/linux/linux_vdso_inc.S
+++ b/sys/compat/linux/linux_vdso_inc.S
@@ -37,3 +37,5 @@ _binary_linux_vdso_so_o_end:
#include <machine/asm.h>
GNU_PROPERTY_AARCH64_FEATURE_1_NOTE(GNU_PROPERTY_AARCH64_FEATURE_1_VAL)
#endif
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/sys/compat/linuxkpi/common/src/linux_acpi.c b/sys/compat/linuxkpi/common/src/linux_acpi.c
index c7d62c745c7e..85a3afe5d01d 100644
--- a/sys/compat/linuxkpi/common/src/linux_acpi.c
+++ b/sys/compat/linuxkpi/common/src/linux_acpi.c
@@ -131,7 +131,7 @@ linux_handle_power_suspend_event(void *arg __unused, enum power_stype stype)
linux_acpi_target_sleep_state = ACPI_STATE_S3;
pm_suspend_target_state = PM_SUSPEND_TO_IDLE;
break;
- case POWER_STYPE_SUSPEND_TO_MEM:
+ case POWER_STYPE_FW_SUSPEND:
linux_acpi_target_sleep_state = ACPI_STATE_S3;
pm_suspend_target_state = PM_SUSPEND_MEM;
break;
diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64
index 44f292d9048f..faecea51d5c1 100644
--- a/sys/conf/files.arm64
+++ b/sys/conf/files.arm64
@@ -9,6 +9,7 @@ kern/subr_devmap.c standard
kern/subr_efi_map.c standard
kern/subr_intr.c optional intrng
kern/subr_physmem.c standard
+kern/subr_busdma_bufalloc.c standard
libkern/strlen.c standard
libkern/arm64/crc32c_armv8.S standard
@@ -77,6 +78,7 @@ arm64/arm64/ptrauth.c standard \
compile-with "${NORMAL_C:N-mbranch-protection*} -mbranch-protection=bti"
arm64/arm64/pmap.c standard
arm64/arm64/ptrace_machdep.c standard
+arm64/arm64/rsi.c standard
arm64/arm64/sdt_machdep.c optional kdtrace_hooks
arm64/arm64/sigtramp.S standard
arm64/arm64/spec_workaround.c standard
diff --git a/sys/conf/files.riscv b/sys/conf/files.riscv
index 90a74367a54f..58a31b5f326e 100644
--- a/sys/conf/files.riscv
+++ b/sys/conf/files.riscv
@@ -6,6 +6,7 @@ cddl/dev/fbt/riscv/fbt_isa.c optional dtrace_fbt | dtraceall compile-with "${
crypto/des/des_enc.c optional netsmb
dev/cpufreq/cpufreq_dt.c optional cpufreq fdt
dev/ofw/ofw_cpu.c optional fdt
+dev/ofw/ofw_pci.c optional pci fdt
dev/ofw/ofw_pcib.c optional pci fdt
dev/pci/pci_dw.c optional pci fdt
dev/pci/pci_dw_if.m optional pci fdt
@@ -42,6 +43,14 @@ libkern/memset.c standard
libkern/strcmp.c standard
libkern/strlen.c standard
libkern/strncmp.c standard
+riscv/iommu/iommu_frontend.c standard
+riscv/iommu/iommu_if.m standard
+riscv/iommu/iommu.c standard
+riscv/iommu/iommu_fdt.c optional fdt
+riscv/iommu/iommu_pci.c optional pci
+riscv/iommu/iommu_pmap.c optional iommu
+dev/iommu/busdma_iommu.c optional iommu
+dev/iommu/iommu_gas.c optional iommu
riscv/riscv/aplic.c standard
riscv/riscv/autoconf.c standard
riscv/riscv/bus_machdep.c standard
diff --git a/sys/contrib/dev/acpica/changes.txt b/sys/contrib/dev/acpica/changes.txt
index 2c13c692d194..9c1952e49d50 100644
--- a/sys/contrib/dev/acpica/changes.txt
+++ b/sys/contrib/dev/acpica/changes.txt
@@ -1,4 +1,28 @@
----------------------------------------
+8 April 2026. Summary of changes for version 20260804:
+
+Major changes:
+
+• ACPI Table Enhancements:
+Updated IORT and MADT template compilations to add new IWB and GICv5 translator/router/ITS entries. Introduced full support for the new DTPR table, including compiler and disassembler handling, template fixes, and register structure refinements. — Jose Marinho and Michal Camacho Romero
+
+• Expanded IDs, GUIDs, and Methods:
+Added Framework Computer Hardware IDs, modern standby _DSM GUIDs, and TPM2 start methods. Updated _DSM Arg3 formatting and _CPC handling to align with newer ACPI specifications and avoid Linux compatibility warnings. — Daniel Schaefer and Saket Dumbre
+
+• Compiler, Disassembler, and Tooling Improvements:
+Enhanced the ASL compiler and disassembler with External() deduplication, alias node support, improved validation of malformed inputs, and comma-separated Package output. Updated acpisrc to recognize missing structures and improved parse tree walk termination logic. — ikaros and Pawel Chmielewski
+
+• Security and Stability Fixes:
+Fixed multiple critical issues, including heap-buffer-overflows, use-after-free, NULL pointer dereferences, integer overflows, and out-of-bounds accesses across AML parsing, interpretation, and table handling code paths. — ikaros and Weiming Shi
+
+• Resource and Register Refactoring:
+Corrected I2C LVR resource descriptor handling and refactored TPR Base/Limit registers to use compatible bitmask representations, with additional validation and cleanup across DTPR-related code. — Akhil R and Michal Camacho Romero
+
+• General Cleanup and Build Fixes:
+Fixed a syntax error caused by a stray character, corrected spelling issues, improved comment alignment and formatting, updated dummy compiler metadata, and disabled excessive MSVC bitfield warnings (C4214) to improve build clarity. — Colin Ian King and Saket Dumbre
+
+
+----------------------------------------
12 December 2025. Summary of changes for version 20251212:
Major changes:
diff --git a/sys/contrib/dev/acpica/common/acfileio.c b/sys/contrib/dev/acpica/common/acfileio.c
index 19274cb4bdd3..4ae0db12b09b 100644
--- a/sys/contrib/dev/acpica/common/acfileio.c
+++ b/sys/contrib/dev/acpica/common/acfileio.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -452,6 +452,15 @@ AcGetOneTableFromFile (
TableLength = TableHeader.Length;
}
+ /* Table length must be at least large enough to hold the header */
+
+ if (TableLength < HeaderLength)
+ {
+ fprintf (stderr, "Table length too small for header: 0x%.2X\n",
+ TableLength);
+ return (AE_BAD_HEADER);
+ }
+
/* Allocate a buffer for the entire table */
Table = AcpiOsAllocate ((ACPI_SIZE) TableLength);
diff --git a/sys/contrib/dev/acpica/common/acgetline.c b/sys/contrib/dev/acpica/common/acgetline.c
index 2793f26077bb..8ad4f5174d41 100644
--- a/sys/contrib/dev/acpica/common/acgetline.c
+++ b/sys/contrib/dev/acpica/common/acgetline.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/common/adfile.c b/sys/contrib/dev/acpica/common/adfile.c
index f87b329d918d..dbf0eaeb2a2e 100644
--- a/sys/contrib/dev/acpica/common/adfile.c
+++ b/sys/contrib/dev/acpica/common/adfile.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/common/adisasm.c b/sys/contrib/dev/acpica/common/adisasm.c
index 83125098cbd1..7016d46dc849 100644
--- a/sys/contrib/dev/acpica/common/adisasm.c
+++ b/sys/contrib/dev/acpica/common/adisasm.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/common/adwalk.c b/sys/contrib/dev/acpica/common/adwalk.c
index b7484315fe51..cd5c2b1d0911 100644
--- a/sys/contrib/dev/acpica/common/adwalk.c
+++ b/sys/contrib/dev/acpica/common/adwalk.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/common/ahids.c b/sys/contrib/dev/acpica/common/ahids.c
index 81b21253feef..7f011ec10201 100644
--- a/sys/contrib/dev/acpica/common/ahids.c
+++ b/sys/contrib/dev/acpica/common/ahids.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -202,6 +202,14 @@ const AH_DEVICE_ID AslDeviceIds[] =
{"CPLM3218", "Capella Micro CM3218x Ambient Light Sensor"},
{"DELLABCE", "Dell Airplane Mode Switch Driver"},
{"DLAC3002", "Qualcomm Atheros Bluetooth UART Transport"},
+ {"FRMW0001", "Framework I2C HID from EC (Laptop 13 Intel 11-13th Gen)"},
+ {"FRMW0002", "Framework PS2 Touchpad Emulation"},
+ {"FRMW0003", "Framework I2C HID from EC (Laptop 16 AMD Ryzen 7040)"},
+ {"FRMW0004", "Framework I2C HID from EC for keyboard media ikeys"},
+ {"FRMW0005", "Framework I2C HID from EC for ALS Sensor"},
+ {"FRMW0006", "Framework Desktop ARGB HID Interface (Chrome EC RGBKBD)"},
+ {"FRMWC004", "Framework EC Controller"},
+ {"FRMWC006", "Framework EC Sensor Hub"},
{"FTTH5506", "FocalTech 5506 Touch Controller"},
{"HAD0F28", "Intel HDMI Audio Driver"},
{"INBC0000", "GPIO Expander"},
diff --git a/sys/contrib/dev/acpica/common/ahpredef.c b/sys/contrib/dev/acpica/common/ahpredef.c
index 3a94a24897ae..10a56aba7dc9 100644
--- a/sys/contrib/dev/acpica/common/ahpredef.c
+++ b/sys/contrib/dev/acpica/common/ahpredef.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/common/ahtable.c b/sys/contrib/dev/acpica/common/ahtable.c
index 109a723fd93d..7bde21e2264e 100644
--- a/sys/contrib/dev/acpica/common/ahtable.c
+++ b/sys/contrib/dev/acpica/common/ahtable.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -216,6 +216,7 @@ const AH_TABLE AcpiGbl_SupportedTables[] =
{ACPI_SIG_DBGP, "Debug Port Table"},
{ACPI_SIG_DMAR, "DMA Remapping Table"},
{ACPI_SIG_DRTM, "Dynamic Root of Trust for Measurement Table"},
+ {ACPI_SIG_DTPR, "DMA TXT Protection Ranges Table"},
{ACPI_SIG_DSDT, "Differentiated System Description Table (AML table)"},
{ACPI_SIG_ECDT, "Embedded Controller Boot Resources Table"},
{ACPI_SIG_EINJ, "Error Injection Table"},
diff --git a/sys/contrib/dev/acpica/common/ahuuids.c b/sys/contrib/dev/acpica/common/ahuuids.c
index b87de1cdff82..40906109ae3e 100644
--- a/sys/contrib/dev/acpica/common/ahuuids.c
+++ b/sys/contrib/dev/acpica/common/ahuuids.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -204,6 +204,11 @@ const AH_UUID Gbl_AcpiUuids[] =
{"Cache Properties", UUID_CACHE_PROPERTIES},
{"Physical Package Property", UUID_PHYSICAL_PROPERTY},
+ {"[Modern Standby]", NULL},
+ {"Modern Standby Microsoft", UUID_LPS0_MICROSOFT},
+ {"Modern Standby Intel", UUID_LPS0_INTEL},
+ {"Modern Standby AMD", UUID_LPS0_AMD},
+
{"[Miscellaneous]", NULL},
{"Platform-wide Capabilities", UUID_PLATFORM_CAPABILITIES},
{"Dynamic Enumeration", UUID_DYNAMIC_ENUMERATION},
diff --git a/sys/contrib/dev/acpica/common/cmfsize.c b/sys/contrib/dev/acpica/common/cmfsize.c
index c6cedf9a0866..8e6bee607564 100644
--- a/sys/contrib/dev/acpica/common/cmfsize.c
+++ b/sys/contrib/dev/acpica/common/cmfsize.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/common/dmextern.c b/sys/contrib/dev/acpica/common/dmextern.c
index d2eeffdfe02e..405139beb815 100644
--- a/sys/contrib/dev/acpica/common/dmextern.c
+++ b/sys/contrib/dev/acpica/common/dmextern.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/common/dmrestag.c b/sys/contrib/dev/acpica/common/dmrestag.c
index 8c7cc4b9ef7c..95300444b9dc 100644
--- a/sys/contrib/dev/acpica/common/dmrestag.c
+++ b/sys/contrib/dev/acpica/common/dmrestag.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/common/dmswitch.c b/sys/contrib/dev/acpica/common/dmswitch.c
index 8d5ca2e016a7..9d7b48ccacd4 100644
--- a/sys/contrib/dev/acpica/common/dmswitch.c
+++ b/sys/contrib/dev/acpica/common/dmswitch.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/common/dmtable.c b/sys/contrib/dev/acpica/common/dmtable.c
index 140d279a486c..d7a42323c20c 100644
--- a/sys/contrib/dev/acpica/common/dmtable.c
+++ b/sys/contrib/dev/acpica/common/dmtable.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -568,6 +568,10 @@ static const char *AcpiDmTpm2Subnames[] =
"Reserved",
"Reserved",
"Command Response Buffer with ARM SMC",
+ "FIFO over I2C",
+ "Command Response Buffer with AMD Mailbox",
+ "Reserved",
+ "Command Response Buffer with ARM Framework-A",
"Unknown Subtable Type" /* Reserved */
};
@@ -700,6 +704,7 @@ const ACPI_DMTABLE_DATA AcpiDmTableData[] =
{ACPI_SIG_DBGP, AcpiDmTableInfoDbgp, NULL, NULL, TemplateDbgp},
{ACPI_SIG_DMAR, NULL, AcpiDmDumpDmar, DtCompileDmar, TemplateDmar},
{ACPI_SIG_DRTM, NULL, AcpiDmDumpDrtm, DtCompileDrtm, TemplateDrtm},
+ {ACPI_SIG_DTPR, NULL, AcpiDmDumpDtpr, DtCompileDtpr, TemplateDtpr},
{ACPI_SIG_ECDT, AcpiDmTableInfoEcdt, NULL, NULL, TemplateEcdt},
{ACPI_SIG_EINJ, NULL, AcpiDmDumpEinj, DtCompileEinj, TemplateEinj},
{ACPI_SIG_ERDT, NULL, AcpiDmDumpErdt, DtCompileErdt, TemplateErdt},
diff --git a/sys/contrib/dev/acpica/common/dmtables.c b/sys/contrib/dev/acpica/common/dmtables.c
index c72f6451154c..8ec0077c3c38 100644
--- a/sys/contrib/dev/acpica/common/dmtables.c
+++ b/sys/contrib/dev/acpica/common/dmtables.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/common/dmtbdump.c b/sys/contrib/dev/acpica/common/dmtbdump.c
index aa8b5aa76892..bb4f75b70aeb 100644
--- a/sys/contrib/dev/acpica/common/dmtbdump.c
+++ b/sys/contrib/dev/acpica/common/dmtbdump.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/common/dmtbdump1.c b/sys/contrib/dev/acpica/common/dmtbdump1.c
index 3453ed479a22..5d2758c49acc 100644
--- a/sys/contrib/dev/acpica/common/dmtbdump1.c
+++ b/sys/contrib/dev/acpica/common/dmtbdump1.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -1672,6 +1672,115 @@ AcpiDmDumpDrtm (
/*******************************************************************************
*
+ * FUNCTION: AcpiDmDumpDtpr
+ *
+ * PARAMETERS: Table - A DTPR table
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Format the contents of a DTPR.
+ *
+ ******************************************************************************/
+
+void
+AcpiDmDumpDtpr (
+ ACPI_TABLE_HEADER *Table)
+{
+ ACPI_STATUS Status;
+ ACPI_TPR_ARRAY *TprArr;
+ ACPI_TPR_INSTANCE *TprInstance;
+ ACPI_TPR_AUX_SR *TprAuxSr;
+ ACPI_TPR_SERIALIZE_REQUEST *TprSerializeRequest;
+ UINT32 i = 0, j, InsCnt, TprRefCnt;
+ UINT32 Offset = sizeof(ACPI_TABLE_DTPR);
+
+ /* Main table */
+
+ Status = AcpiDmDumpTable (Table->Length, 0, Table, 0, AcpiDmTableInfoDtpr);
+ if (ACPI_FAILURE (Status))
+ {
+ return;
+ }
+
+ /* Subtables */
+
+ while (Offset < Table->Length)
+ {
+ InsCnt = ((ACPI_TABLE_DTPR*) Table)->InsCnt;
+
+ for (i = 0; i < InsCnt; i++)
+ {
+ TprInstance = ACPI_ADD_PTR(ACPI_TPR_INSTANCE, Table, Offset);
+ Status = AcpiDmDumpTable(Table->Length, Offset, TprInstance,
+ sizeof(ACPI_TPR_INSTANCE), AcpiDmTableInfoDtprInstance);
+ if (ACPI_FAILURE (Status))
+ {
+ return;
+ }
+
+ /* Each of the TPR instances must have the same number of TPRs*/
+ TprRefCnt = TprInstance->TprCnt;
+
+ Offset += sizeof(ACPI_TPR_INSTANCE);
+
+ if (TprInstance->TprCnt < 2)
+ {
+ AcpiOsPrintf("TPR Instance No.%d has invalid number of TPRs.\n"
+ "There should be at least 2 of them, but there is %d.",
+ i, TprInstance->TprCnt);
+ return;
+ }
+ else
+ {
+ if (TprInstance->TprCnt != TprRefCnt)
+ {
+ AcpiOsPrintf("Each of TPR instances should have equal\n"
+ "number of TPRs. TprInstance No.%d has %d TPRs"
+ ", while the reference TPR instance has %d.\n",
+ i, TprInstance->TprCnt, TprRefCnt);
+ return;
+ }
+ }
+
+ for (j = 0; j < TprInstance->TprCnt; j++)
+ {
+ TprArr = ACPI_ADD_PTR(ACPI_TPR_ARRAY, Table, Offset);
+ Status = AcpiDmDumpTable(Table->Length, Offset, TprArr,
+ sizeof(ACPI_TPR_ARRAY), AcpiDmTableInfoDtprArr);
+ if (ACPI_FAILURE (Status))
+ {
+ return;
+ }
+
+ Offset += sizeof(ACPI_TPR_ARRAY);
+ }
+ }
+
+ TprAuxSr = ACPI_ADD_PTR(ACPI_TPR_AUX_SR, Table, Offset);
+ Status = AcpiDmDumpTable(Table->Length, Offset, TprAuxSr,
+ sizeof(ACPI_TPR_AUX_SR), AcpiDmTableInfoDtprSerializeReq0);
+
+ Offset += sizeof(ACPI_TPR_AUX_SR);
+
+ for (i = 0; i < TprAuxSr->SrlCnt; i++)
+ {
+ TprSerializeRequest = ACPI_ADD_PTR(ACPI_TPR_SERIALIZE_REQUEST,
+ Table, Offset);
+ Status = AcpiDmDumpTable(Table->Length, Offset, TprSerializeRequest,
+ sizeof(ACPI_TPR_SERIALIZE_REQUEST), AcpiDmTableInfoDtprSerializeReq1);
+ if (ACPI_FAILURE (Status))
+ {
+ return;
+ }
+
+ Offset += sizeof(ACPI_TPR_SERIALIZE_REQUEST);
+ }
+ }
+}
+
+
+/*******************************************************************************
+ *
* FUNCTION: AcpiDmDumpEinj
*
* PARAMETERS: Table - A EINJ table
diff --git a/sys/contrib/dev/acpica/common/dmtbdump2.c b/sys/contrib/dev/acpica/common/dmtbdump2.c
index 957b3b00f216..21309e9c7869 100644
--- a/sys/contrib/dev/acpica/common/dmtbdump2.c
+++ b/sys/contrib/dev/acpica/common/dmtbdump2.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/common/dmtbdump3.c b/sys/contrib/dev/acpica/common/dmtbdump3.c
index 458b94f6ee08..e827bf8e50cc 100644
--- a/sys/contrib/dev/acpica/common/dmtbdump3.c
+++ b/sys/contrib/dev/acpica/common/dmtbdump3.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/common/dmtbinfo.c b/sys/contrib/dev/acpica/common/dmtbinfo.c
index 937ad013f079..afa3115fcbdc 100644
--- a/sys/contrib/dev/acpica/common/dmtbinfo.c
+++ b/sys/contrib/dev/acpica/common/dmtbinfo.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/common/dmtbinfo1.c b/sys/contrib/dev/acpica/common/dmtbinfo1.c
index 49c0f6f2a31c..40d6dfc27a71 100644
--- a/sys/contrib/dev/acpica/common/dmtbinfo1.c
+++ b/sys/contrib/dev/acpica/common/dmtbinfo1.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -1155,6 +1155,44 @@ ACPI_DMTABLE_INFO AcpiDmTableInfoDrtm2[] =
/*******************************************************************************
*
+ * DTPR - DMA TXT Protection Ranges Table
+ *
+ ******************************************************************************/
+
+ACPI_DMTABLE_INFO AcpiDmTableInfoDtpr[] =
+{
+ {ACPI_DMT_UINT32, ACPI_DTPR_OFFSET (Flags), "Flags (reserved)", 0},
+ {ACPI_DMT_UINT32, ACPI_DTPR_OFFSET (InsCnt), "Instance Count", 0},
+ ACPI_DMT_TERMINATOR
+};
+
+ACPI_DMTABLE_INFO AcpiDmTableInfoDtprInstance[] =
+{
+ {ACPI_DMT_UINT32, ACPI_DTPR_INST_OFFSET (Flags), "Instance control flags (reserved)", 0},
+ {ACPI_DMT_UINT32, ACPI_DTPR_INST_OFFSET (TprCnt), "Number of TPR ranges in instance", 0},
+ ACPI_DMT_TERMINATOR
+};
+
+ACPI_DMTABLE_INFO AcpiDmTableInfoDtprArr[] =
+{
+ {ACPI_DMT_UINT64, ACPI_DTPR_ARR_OFFSET (Base), "TPR Base Address", 0},
+ ACPI_DMT_TERMINATOR
+};
+
+ACPI_DMTABLE_INFO AcpiDmTableInfoDtprSerializeReq0[] =
+{
+ {ACPI_DMT_UINT32, ACPI_DTPR_AUX_SR_OFFSET (SrlCnt), "Number of serialization registers", 0},
+ ACPI_DMT_TERMINATOR
+};
+
+ACPI_DMTABLE_INFO AcpiDmTableInfoDtprSerializeReq1[] =
+{
+ {ACPI_DMT_UINT64, ACPI_DTPR_SR_OFFSET (SrRegister), "Serialize Request register", 0},
+ ACPI_DMT_TERMINATOR
+};
+
+/*******************************************************************************
+ *
* ECDT - Embedded Controller Boot Resources Table
*
******************************************************************************/
diff --git a/sys/contrib/dev/acpica/common/dmtbinfo2.c b/sys/contrib/dev/acpica/common/dmtbinfo2.c
index d4ebc9f49074..fd6a11a7aa84 100644
--- a/sys/contrib/dev/acpica/common/dmtbinfo2.c
+++ b/sys/contrib/dev/acpica/common/dmtbinfo2.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -1243,7 +1243,7 @@ ACPI_DMTABLE_INFO AcpiDmTableInfoMadt30[] =
{
{ACPI_DMT_UINT16, ACPI_MADT30_OFFSET (Reserved), "Reserved", 0},
{ACPI_DMT_UINT32, ACPI_MADT30_OFFSET (LinkedTranslatorId), "Linked Its Id", 0},
- {ACPI_DMT_UINT32, ACPI_MADT30_OFFSET (TranslateFrameId), "Its Transalte Id", 0},
+ {ACPI_DMT_UINT32, ACPI_MADT30_OFFSET (TranslateFrameId), "Its Translate Id", 0},
{ACPI_DMT_UINT32, ACPI_MADT30_OFFSET (Reserved2), "Reserved", 0},
{ACPI_DMT_UINT64, ACPI_MADT30_OFFSET (BaseAddress), "Its Translate Frame Physical Base Address", 0},
ACPI_DMT_TERMINATOR
diff --git a/sys/contrib/dev/acpica/common/dmtbinfo3.c b/sys/contrib/dev/acpica/common/dmtbinfo3.c
index d7cdc90cd993..88728e27a698 100644
--- a/sys/contrib/dev/acpica/common/dmtbinfo3.c
+++ b/sys/contrib/dev/acpica/common/dmtbinfo3.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/common/getopt.c b/sys/contrib/dev/acpica/common/getopt.c
index 535e7a00bc8f..3af472ffe13d 100644
--- a/sys/contrib/dev/acpica/common/getopt.c
+++ b/sys/contrib/dev/acpica/common/getopt.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslallocate.c b/sys/contrib/dev/acpica/compiler/aslallocate.c
index 57e538b534e5..4d0aef2b4142 100644
--- a/sys/contrib/dev/acpica/compiler/aslallocate.c
+++ b/sys/contrib/dev/acpica/compiler/aslallocate.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslanalyze.c b/sys/contrib/dev/acpica/compiler/aslanalyze.c
index 625611a630de..015119ba4e78 100644
--- a/sys/contrib/dev/acpica/compiler/aslanalyze.c
+++ b/sys/contrib/dev/acpica/compiler/aslanalyze.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslascii.c b/sys/contrib/dev/acpica/compiler/aslascii.c
index 1de3d763c765..700ad30045f2 100644
--- a/sys/contrib/dev/acpica/compiler/aslascii.c
+++ b/sys/contrib/dev/acpica/compiler/aslascii.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslbtypes.c b/sys/contrib/dev/acpica/compiler/aslbtypes.c
index 539cd7977b4e..a11b1f465d9e 100644
--- a/sys/contrib/dev/acpica/compiler/aslbtypes.c
+++ b/sys/contrib/dev/acpica/compiler/aslbtypes.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslcache.c b/sys/contrib/dev/acpica/compiler/aslcache.c
index 9f917ff32945..93309f90093f 100644
--- a/sys/contrib/dev/acpica/compiler/aslcache.c
+++ b/sys/contrib/dev/acpica/compiler/aslcache.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslcodegen.c b/sys/contrib/dev/acpica/compiler/aslcodegen.c
index 684c59f802e9..f329f3738f8b 100644
--- a/sys/contrib/dev/acpica/compiler/aslcodegen.c
+++ b/sys/contrib/dev/acpica/compiler/aslcodegen.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -586,14 +586,16 @@ CgWriteTableHeader (
/* OEMID */
Child = Child->Asl.Next;
- memcpy (AslGbl_TableHeader.OemId, Child->Asl.Value.String,
- strlen (Child->Asl.Value.String));
+ /* Bound copy to header field size to avoid overflow on malformed input */
+ strncpy (AslGbl_TableHeader.OemId, Child->Asl.Value.String,
+ ACPI_OEM_ID_SIZE);
/* OEM TableID */
Child = Child->Asl.Next;
- memcpy (AslGbl_TableHeader.OemTableId, Child->Asl.Value.String,
- strlen (Child->Asl.Value.String));
+ /* Bound copy to header field size to avoid overflow on malformed input */
+ strncpy (AslGbl_TableHeader.OemTableId, Child->Asl.Value.String,
+ ACPI_OEM_TABLE_ID_SIZE);
/* OEM Revision */
diff --git a/sys/contrib/dev/acpica/compiler/aslcompile.c b/sys/contrib/dev/acpica/compiler/aslcompile.c
index 6e8ce6aae2c9..696da41ba46d 100644
--- a/sys/contrib/dev/acpica/compiler/aslcompile.c
+++ b/sys/contrib/dev/acpica/compiler/aslcompile.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslcompiler.h b/sys/contrib/dev/acpica/compiler/aslcompiler.h
index d131b949252a..d877357d4345 100644
--- a/sys/contrib/dev/acpica/compiler/aslcompiler.h
+++ b/sys/contrib/dev/acpica/compiler/aslcompiler.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslcompiler.l b/sys/contrib/dev/acpica/compiler/aslcompiler.l
index 5e94f9626018..bde40db4c00e 100644
--- a/sys/contrib/dev/acpica/compiler/aslcompiler.l
+++ b/sys/contrib/dev/acpica/compiler/aslcompiler.l
@@ -9,7 +9,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslcstyle.y b/sys/contrib/dev/acpica/compiler/aslcstyle.y
index 59a1abea1bee..6384a1e932d6 100644
--- a/sys/contrib/dev/acpica/compiler/aslcstyle.y
+++ b/sys/contrib/dev/acpica/compiler/aslcstyle.y
@@ -9,7 +9,7 @@ NoEcho('
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/asldebug.c b/sys/contrib/dev/acpica/compiler/asldebug.c
index 18b68dea6de0..bb5e0bbdb047 100644
--- a/sys/contrib/dev/acpica/compiler/asldebug.c
+++ b/sys/contrib/dev/acpica/compiler/asldebug.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/asldefine.h b/sys/contrib/dev/acpica/compiler/asldefine.h
index 89b6b8a69956..5f694efe40df 100644
--- a/sys/contrib/dev/acpica/compiler/asldefine.h
+++ b/sys/contrib/dev/acpica/compiler/asldefine.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslerror.c b/sys/contrib/dev/acpica/compiler/aslerror.c
index ff01bef7b4b7..6612af39fa94 100644
--- a/sys/contrib/dev/acpica/compiler/aslerror.c
+++ b/sys/contrib/dev/acpica/compiler/aslerror.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslexternal.c b/sys/contrib/dev/acpica/compiler/aslexternal.c
index e2f082593c5d..83ba04f573f5 100644
--- a/sys/contrib/dev/acpica/compiler/aslexternal.c
+++ b/sys/contrib/dev/acpica/compiler/aslexternal.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -170,6 +170,10 @@ static void
ExMoveExternals (
ACPI_PARSE_OBJECT *DefinitionBlockOp);
+static void
+ExRemoveOpFromTree (
+ ACPI_PARSE_OBJECT *Op);
+
/*******************************************************************************
*
@@ -194,9 +198,14 @@ ExDoExternal (
ACPI_PARSE_OBJECT *ArgCountOp;
ACPI_PARSE_OBJECT *TypeOp;
ACPI_PARSE_OBJECT *ExternTypeOp = Op->Asl.Child->Asl.Next;
+ ACPI_PARSE_OBJECT *Existing;
+ ACPI_PARSE_OBJECT *NameOp = Op->Asl.Child;
+ ACPI_PARSE_OBJECT *ExistingNameOp;
UINT32 ExternType;
UINT8 ParamCount = ASL_EXTERNAL_METHOD_UNKNOWN_PARAMS;
UINT32 ParamTypes[ACPI_METHOD_NUM_ARGS];
+ char *NewPath = NULL;
+ char *ExistingPath;
ExternType = AnMapObjTypeToBtype (ExternTypeOp);
@@ -250,6 +259,53 @@ ExDoExternal (
ArgCountOp->Asl.Value.Integer = ParamCount;
UtSetParseOpName (ArgCountOp);
+ /*
+ * Deduplicate identical External() declarations. The disassembler
+ * already collapses duplicates; mirror that behavior in the compiler
+ * so duplicate externals do not bloat emitted AML.
+ */
+
+ NewPath = NameOp->Asl.Namepath;
+ if (!NewPath && NameOp->Asl.Value.String)
+ {
+ (void) UtInternalizeName (NameOp->Asl.Value.String, &NewPath);
+ NameOp->Asl.Namepath = NewPath;
+ }
+
+ Existing = AslGbl_ExternalsListHead;
+ while (Existing && NewPath)
+ {
+ ExistingNameOp = Existing->Asl.Child->Asl.Child;
+ ExistingPath = ExistingNameOp->Asl.Namepath;
+ if (!ExistingPath && ExistingNameOp->Asl.Value.String)
+ {
+ (void) UtInternalizeName (ExistingNameOp->Asl.Value.String,
+ &ExistingPath);
+ ExistingNameOp->Asl.Namepath = ExistingPath;
+ }
+
+ if (ExistingPath && !strcmp (NewPath, ExistingPath))
+ {
+ ACPI_PARSE_OBJECT *ExistingArgCount;
+
+ /* Update arg count if this instance is more specific */
+
+ ExistingArgCount = Existing->Asl.Child->Asl.Child->Asl.Next->Asl.Next;
+ if ((ExternType == ACPI_BTYPE_METHOD) &&
+ (ParamCount < ExistingArgCount->Asl.Value.Integer))
+ {
+ ExistingArgCount->Asl.Value.Integer = ParamCount;
+ }
+
+ /* Remove duplicate External node from the parse tree */
+
+ ExRemoveOpFromTree (Op);
+ return;
+ }
+
+ Existing = Existing->Asl.Next;
+ }
+
/* Create new list node of arbitrary type */
ListOp = TrAllocateOp (PARSEOP_DEFAULT_ARG);
@@ -282,6 +338,53 @@ ExDoExternal (
/*******************************************************************************
*
+ * FUNCTION: ExRemoveOpFromTree
+ *
+ * PARAMETERS: Op - Parse op to remove from the tree
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Unlink a parse op from its parent sibling list. Used to drop
+ * duplicate External() declarations before AML emission.
+ *
+ ******************************************************************************/
+
+static void
+ExRemoveOpFromTree (
+ ACPI_PARSE_OBJECT *Op)
+{
+ ACPI_PARSE_OBJECT *Parent;
+ ACPI_PARSE_OBJECT *Child;
+
+
+ if (!Op || !Op->Asl.Parent)
+ {
+ return;
+ }
+
+ Parent = Op->Asl.Parent;
+ Child = Parent->Asl.Child;
+
+ if (Child == Op)
+ {
+ Parent->Asl.Child = Op->Asl.Next;
+ return;
+ }
+
+ while (Child && Child->Asl.Next != Op)
+ {
+ Child = Child->Asl.Next;
+ }
+
+ if (Child)
+ {
+ Child->Asl.Next = Op->Asl.Next;
+ }
+}
+
+
+/*******************************************************************************
+ *
* FUNCTION: ExInsertArgCount
*
* PARAMETERS: Op - Op for a method invocation
diff --git a/sys/contrib/dev/acpica/compiler/aslfileio.c b/sys/contrib/dev/acpica/compiler/aslfileio.c
index 4bf18404b1f5..e3dfaa6ebf6e 100644
--- a/sys/contrib/dev/acpica/compiler/aslfileio.c
+++ b/sys/contrib/dev/acpica/compiler/aslfileio.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslfiles.c b/sys/contrib/dev/acpica/compiler/aslfiles.c
index 0cad8eff47e8..4528d17764f0 100644
--- a/sys/contrib/dev/acpica/compiler/aslfiles.c
+++ b/sys/contrib/dev/acpica/compiler/aslfiles.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslfold.c b/sys/contrib/dev/acpica/compiler/aslfold.c
index 89107297588b..ecf4c683b78b 100644
--- a/sys/contrib/dev/acpica/compiler/aslfold.c
+++ b/sys/contrib/dev/acpica/compiler/aslfold.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslglobal.h b/sys/contrib/dev/acpica/compiler/aslglobal.h
index c79758919f6f..0f2d5931cec8 100644
--- a/sys/contrib/dev/acpica/compiler/aslglobal.h
+++ b/sys/contrib/dev/acpica/compiler/aslglobal.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -252,6 +252,7 @@ extern FILE *AslCompilerin;
extern int DtParserdebug;
extern int PrParserdebug;
extern const ASL_MAPPING_ENTRY AslKeywordMapping[];
+extern const UINT32 AslKeywordMappingCount;
extern char *AslCompilertext;
extern char *DtCompilerParsertext;
diff --git a/sys/contrib/dev/acpica/compiler/aslhelp.c b/sys/contrib/dev/acpica/compiler/aslhelp.c
index fcec07e67e70..0f6421ceba97 100644
--- a/sys/contrib/dev/acpica/compiler/aslhelp.c
+++ b/sys/contrib/dev/acpica/compiler/aslhelp.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslhelpers.y b/sys/contrib/dev/acpica/compiler/aslhelpers.y
index cb13d1ebcfe7..728ea9bd810c 100644
--- a/sys/contrib/dev/acpica/compiler/aslhelpers.y
+++ b/sys/contrib/dev/acpica/compiler/aslhelpers.y
@@ -9,7 +9,7 @@ NoEcho('
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslhex.c b/sys/contrib/dev/acpica/compiler/aslhex.c
index 927e50f24c1d..e0d8831e2a4a 100644
--- a/sys/contrib/dev/acpica/compiler/aslhex.c
+++ b/sys/contrib/dev/acpica/compiler/aslhex.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslkeywords.y b/sys/contrib/dev/acpica/compiler/aslkeywords.y
index 7cb670e61bfb..bdd42231cf55 100644
--- a/sys/contrib/dev/acpica/compiler/aslkeywords.y
+++ b/sys/contrib/dev/acpica/compiler/aslkeywords.y
@@ -9,7 +9,7 @@ NoEcho('
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/asllength.c b/sys/contrib/dev/acpica/compiler/asllength.c
index 136ca5823001..e2acc91755b9 100644
--- a/sys/contrib/dev/acpica/compiler/asllength.c
+++ b/sys/contrib/dev/acpica/compiler/asllength.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/asllisting.c b/sys/contrib/dev/acpica/compiler/asllisting.c
index 2a6341bb59e1..3c76672f0bef 100644
--- a/sys/contrib/dev/acpica/compiler/asllisting.c
+++ b/sys/contrib/dev/acpica/compiler/asllisting.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/asllistsup.c b/sys/contrib/dev/acpica/compiler/asllistsup.c
index 3458e28062de..f173d80de95d 100644
--- a/sys/contrib/dev/acpica/compiler/asllistsup.c
+++ b/sys/contrib/dev/acpica/compiler/asllistsup.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslload.c b/sys/contrib/dev/acpica/compiler/aslload.c
index c88fb13aba78..8aa3dce5b655 100644
--- a/sys/contrib/dev/acpica/compiler/aslload.c
+++ b/sys/contrib/dev/acpica/compiler/aslload.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -1406,6 +1406,8 @@ LdNamespace2Begin (
/* Save the target node within the alias node as well as type information */
+ /* Mark as alias node and store target namespace node */
+ Node->Flags |= ANOBJ_IS_ALIAS;
Node->Object = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, TargetNode);
Node->Type = TargetNode->Type;
if (Node->Type == ACPI_TYPE_METHOD)
diff --git a/sys/contrib/dev/acpica/compiler/asllookup.c b/sys/contrib/dev/acpica/compiler/asllookup.c
index 3dfdb1fce21e..c5885ea85786 100644
--- a/sys/contrib/dev/acpica/compiler/asllookup.c
+++ b/sys/contrib/dev/acpica/compiler/asllookup.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslmain.c b/sys/contrib/dev/acpica/compiler/aslmain.c
index ff22dec73369..21124cd1cabf 100644
--- a/sys/contrib/dev/acpica/compiler/aslmain.c
+++ b/sys/contrib/dev/acpica/compiler/aslmain.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslmap.c b/sys/contrib/dev/acpica/compiler/aslmap.c
index 4711b884a57c..08c1d5bdd36b 100644
--- a/sys/contrib/dev/acpica/compiler/aslmap.c
+++ b/sys/contrib/dev/acpica/compiler/aslmap.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -611,3 +611,5 @@ const ASL_MAPPING_ENTRY AslKeywordMapping [] =
/*! [End] no source code translation !*/
};
+
+const UINT32 AslKeywordMappingCount = ACPI_ARRAY_LENGTH (AslKeywordMapping);
diff --git a/sys/contrib/dev/acpica/compiler/aslmapenter.c b/sys/contrib/dev/acpica/compiler/aslmapenter.c
index 81b57cb3f13d..032d953c596c 100644
--- a/sys/contrib/dev/acpica/compiler/aslmapenter.c
+++ b/sys/contrib/dev/acpica/compiler/aslmapenter.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslmapoutput.c b/sys/contrib/dev/acpica/compiler/aslmapoutput.c
index a009f64bc98d..86299dd5b783 100644
--- a/sys/contrib/dev/acpica/compiler/aslmapoutput.c
+++ b/sys/contrib/dev/acpica/compiler/aslmapoutput.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslmaputils.c b/sys/contrib/dev/acpica/compiler/aslmaputils.c
index f978e6a940b3..bafdca0322ce 100644
--- a/sys/contrib/dev/acpica/compiler/aslmaputils.c
+++ b/sys/contrib/dev/acpica/compiler/aslmaputils.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslmessages.c b/sys/contrib/dev/acpica/compiler/aslmessages.c
index 1e363236a149..f7c121ca990d 100644
--- a/sys/contrib/dev/acpica/compiler/aslmessages.c
+++ b/sys/contrib/dev/acpica/compiler/aslmessages.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -412,7 +412,8 @@ const char *AslTableCompilerMsgs [] =
/* ASL_MSG_UNKNOWN_FORMAT */ "Unknown format value",
/* ASL_MSG_RESERVED_VALUE */ "Value for field is reserved or unknown",
/* ASL_MSG_TWO_ZERO_VALUES */ "32-bit DSDT Address and 64-bit X_DSDT Address cannot both be zero",
-/* ASL_MSG_BAD_PARSE_TREE */ "Parse tree appears to be ill-defined"
+/* ASL_MSG_BAD_PARSE_TREE */ "Parse tree appears to be ill-defined",
+/* ASL_MSG_MALFORMED_HEADER */ "Malformed ACPI table header detected"
};
/* Preprocessor */
diff --git a/sys/contrib/dev/acpica/compiler/aslmessages.h b/sys/contrib/dev/acpica/compiler/aslmessages.h
index dc0bbe10bd0d..f8ef09bbe9d3 100644
--- a/sys/contrib/dev/acpica/compiler/aslmessages.h
+++ b/sys/contrib/dev/acpica/compiler/aslmessages.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -414,6 +414,7 @@ typedef enum
ASL_MSG_RESERVED_VALUE,
ASL_MSG_TWO_ZERO_VALUES,
ASL_MSG_BAD_PARSE_TREE,
+ ASL_MSG_MALFORMED_HEADER,
/* These messages are used by the Preprocessor only */
diff --git a/sys/contrib/dev/acpica/compiler/aslmethod.c b/sys/contrib/dev/acpica/compiler/aslmethod.c
index 75096d38999e..6844890ce710 100644
--- a/sys/contrib/dev/acpica/compiler/aslmethod.c
+++ b/sys/contrib/dev/acpica/compiler/aslmethod.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslnamesp.c b/sys/contrib/dev/acpica/compiler/aslnamesp.c
index 9388d7428db6..e15421ec6df2 100644
--- a/sys/contrib/dev/acpica/compiler/aslnamesp.c
+++ b/sys/contrib/dev/acpica/compiler/aslnamesp.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/asloffset.c b/sys/contrib/dev/acpica/compiler/asloffset.c
index d60c4c4ec367..097bedd495fd 100644
--- a/sys/contrib/dev/acpica/compiler/asloffset.c
+++ b/sys/contrib/dev/acpica/compiler/asloffset.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslopcodes.c b/sys/contrib/dev/acpica/compiler/aslopcodes.c
index 8bef46b0d7ae..35f661331a9c 100644
--- a/sys/contrib/dev/acpica/compiler/aslopcodes.c
+++ b/sys/contrib/dev/acpica/compiler/aslopcodes.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -863,6 +863,14 @@ OpcGenerateAmlOpcode (
Index = (UINT16) (Op->Asl.ParseOpcode - ASL_PARSE_OPCODE_BASE);
+ if ((Op->Asl.ParseOpcode < ASL_PARSE_OPCODE_BASE) ||
+ (Index >= AslKeywordMappingCount))
+ {
+ AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op,
+ "Invalid parse opcode in OpcGenerateAmlOpcode");
+ return;
+ }
+
Op->Asl.AmlOpcode = AslKeywordMapping[Index].AmlOpcode;
Op->Asl.AcpiBtype = AslKeywordMapping[Index].AcpiBtype;
Op->Asl.CompileFlags |= AslKeywordMapping[Index].Flags;
diff --git a/sys/contrib/dev/acpica/compiler/asloperands.c b/sys/contrib/dev/acpica/compiler/asloperands.c
index 1978b38b1cff..6e77ae165f87 100644
--- a/sys/contrib/dev/acpica/compiler/asloperands.c
+++ b/sys/contrib/dev/acpica/compiler/asloperands.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -851,7 +851,9 @@ OpnDoPackage (
{
ACPI_PARSE_OBJECT *InitializerOp;
ACPI_PARSE_OBJECT *PackageLengthOp;
+ UINT64 DeclaredLength;
UINT32 PackageLength = 0;
+ UINT32 MaxEncodedLength = 0x0FFFFFFF; /* Max AML package length encoding (28 bits) */
/* Opcode and package length first, followed by the initializer list */
@@ -875,9 +877,21 @@ OpnDoPackage (
/* If package length is a constant, compare to the initializer list */
if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER) ||
- (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST))
+ (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST) ||
+ (PackageLengthOp->Asl.ParseOpcode == PARSEOP_PACKAGE_LENGTH))
{
- if (PackageLengthOp->Asl.Value.Integer > PackageLength)
+ DeclaredLength = PackageLengthOp->Asl.Value.Integer;
+
+ /* Guard against values that cannot be encoded in AML package length format */
+
+ if (DeclaredLength > MaxEncodedLength)
+ {
+ AslError (ASL_ERROR, ASL_MSG_ENCODING_LENGTH, PackageLengthOp, NULL);
+ DeclaredLength = MaxEncodedLength;
+ PackageLengthOp->Asl.Value.Integer = DeclaredLength;
+ }
+
+ if (DeclaredLength > PackageLength)
{
/*
* Allow package length to be longer than the initializer
@@ -891,9 +905,9 @@ OpnDoPackage (
PackageLengthOp, NULL);
}
- PackageLength = (UINT32) PackageLengthOp->Asl.Value.Integer;
+ PackageLength = (UINT32) DeclaredLength;
}
- else if (PackageLengthOp->Asl.Value.Integer < PackageLength)
+ else if (DeclaredLength < PackageLength)
{
/*
* The package length is smaller than the length of the
@@ -999,7 +1013,13 @@ OpnDoLoadTable (
/* Fourth child is the RootPath string */
Next = Next->Asl.Next;
- if (Next->Asl.ParseOpcode == PARSEOP_ZERO)
+ if ((Next->Asl.ParseOpcode == PARSEOP_ZERO) ||
+ ((Next->Asl.Value.Integer == 0) &&
+ ((Next->Asl.ParseOpcode == PARSEOP_INTEGER) ||
+ (Next->Asl.ParseOpcode == PARSEOP_BYTECONST) ||
+ (Next->Asl.ParseOpcode == PARSEOP_WORDCONST) ||
+ (Next->Asl.ParseOpcode == PARSEOP_DWORDCONST)||
+ (Next->Asl.ParseOpcode == PARSEOP_QWORDCONST))))
{
Next->Asl.ParseOpcode = PARSEOP_STRING_LITERAL;
Next->Asl.Value.String = "\\";
diff --git a/sys/contrib/dev/acpica/compiler/aslopt.c b/sys/contrib/dev/acpica/compiler/aslopt.c
index 02d46458d6ac..afd11e06c2ac 100644
--- a/sys/contrib/dev/acpica/compiler/aslopt.c
+++ b/sys/contrib/dev/acpica/compiler/aslopt.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/asloptions.c b/sys/contrib/dev/acpica/compiler/asloptions.c
index a46ce96f5dbd..7c5cb69cf705 100644
--- a/sys/contrib/dev/acpica/compiler/asloptions.c
+++ b/sys/contrib/dev/acpica/compiler/asloptions.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslparseop.c b/sys/contrib/dev/acpica/compiler/aslparseop.c
index 65e5b5b3ea59..c9ffb1d8d850 100644
--- a/sys/contrib/dev/acpica/compiler/aslparseop.c
+++ b/sys/contrib/dev/acpica/compiler/aslparseop.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslparser.y b/sys/contrib/dev/acpica/compiler/aslparser.y
index 65a75af9763c..b29eb2ad0374 100644
--- a/sys/contrib/dev/acpica/compiler/aslparser.y
+++ b/sys/contrib/dev/acpica/compiler/aslparser.y
@@ -9,7 +9,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslpld.c b/sys/contrib/dev/acpica/compiler/aslpld.c
index b1d9a05a7bdc..cfd725a76854 100644
--- a/sys/contrib/dev/acpica/compiler/aslpld.c
+++ b/sys/contrib/dev/acpica/compiler/aslpld.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslpredef.c b/sys/contrib/dev/acpica/compiler/aslpredef.c
index 4125c51c6895..5e1eb160f666 100644
--- a/sys/contrib/dev/acpica/compiler/aslpredef.c
+++ b/sys/contrib/dev/acpica/compiler/aslpredef.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslprepkg.c b/sys/contrib/dev/acpica/compiler/aslprepkg.c
index 9d0e861a0ff9..116aa04976e0 100644
--- a/sys/contrib/dev/acpica/compiler/aslprepkg.c
+++ b/sys/contrib/dev/acpica/compiler/aslprepkg.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslprimaries.y b/sys/contrib/dev/acpica/compiler/aslprimaries.y
index 608009d30da3..ef5aa3a7a8b1 100644
--- a/sys/contrib/dev/acpica/compiler/aslprimaries.y
+++ b/sys/contrib/dev/acpica/compiler/aslprimaries.y
@@ -11,7 +11,7 @@ NoEcho('
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslprintf.c b/sys/contrib/dev/acpica/compiler/aslprintf.c
index 819a498f2b7d..56faa95c6ba5 100644
--- a/sys/contrib/dev/acpica/compiler/aslprintf.c
+++ b/sys/contrib/dev/acpica/compiler/aslprintf.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslprune.c b/sys/contrib/dev/acpica/compiler/aslprune.c
index 4fc3c063f1d6..a8b96f299b60 100644
--- a/sys/contrib/dev/acpica/compiler/aslprune.c
+++ b/sys/contrib/dev/acpica/compiler/aslprune.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslresource.c b/sys/contrib/dev/acpica/compiler/aslresource.c
index 8250e84fd783..6ac8c03089ab 100644
--- a/sys/contrib/dev/acpica/compiler/aslresource.c
+++ b/sys/contrib/dev/acpica/compiler/aslresource.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslresources.y b/sys/contrib/dev/acpica/compiler/aslresources.y
index fd8a33d3c0d6..617a366411fd 100644
--- a/sys/contrib/dev/acpica/compiler/aslresources.y
+++ b/sys/contrib/dev/acpica/compiler/aslresources.y
@@ -11,7 +11,7 @@ NoEcho('
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslrestype1.c b/sys/contrib/dev/acpica/compiler/aslrestype1.c
index 3f873da0e703..c1f5a6885a4f 100644
--- a/sys/contrib/dev/acpica/compiler/aslrestype1.c
+++ b/sys/contrib/dev/acpica/compiler/aslrestype1.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslrestype1i.c b/sys/contrib/dev/acpica/compiler/aslrestype1i.c
index 02f4958d6d51..1ae5e3b0eef6 100644
--- a/sys/contrib/dev/acpica/compiler/aslrestype1i.c
+++ b/sys/contrib/dev/acpica/compiler/aslrestype1i.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslrestype2.c b/sys/contrib/dev/acpica/compiler/aslrestype2.c
index 6fb613370691..7296e2573858 100644
--- a/sys/contrib/dev/acpica/compiler/aslrestype2.c
+++ b/sys/contrib/dev/acpica/compiler/aslrestype2.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslrestype2d.c b/sys/contrib/dev/acpica/compiler/aslrestype2d.c
index 3a7ca9189aff..f392eb6eed7a 100644
--- a/sys/contrib/dev/acpica/compiler/aslrestype2d.c
+++ b/sys/contrib/dev/acpica/compiler/aslrestype2d.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslrestype2e.c b/sys/contrib/dev/acpica/compiler/aslrestype2e.c
index 4e6293617b94..d555fabb4114 100644
--- a/sys/contrib/dev/acpica/compiler/aslrestype2e.c
+++ b/sys/contrib/dev/acpica/compiler/aslrestype2e.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslrestype2q.c b/sys/contrib/dev/acpica/compiler/aslrestype2q.c
index 6ebe149a3c14..489400417f8a 100644
--- a/sys/contrib/dev/acpica/compiler/aslrestype2q.c
+++ b/sys/contrib/dev/acpica/compiler/aslrestype2q.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslrestype2s.c b/sys/contrib/dev/acpica/compiler/aslrestype2s.c
index f47402d4e025..8160114980ed 100644
--- a/sys/contrib/dev/acpica/compiler/aslrestype2s.c
+++ b/sys/contrib/dev/acpica/compiler/aslrestype2s.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslrestype2w.c b/sys/contrib/dev/acpica/compiler/aslrestype2w.c
index cc8a31804977..97a9ad82b5ef 100644
--- a/sys/contrib/dev/acpica/compiler/aslrestype2w.c
+++ b/sys/contrib/dev/acpica/compiler/aslrestype2w.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslrules.y b/sys/contrib/dev/acpica/compiler/aslrules.y
index c96d4cc75db6..00dede690168 100644
--- a/sys/contrib/dev/acpica/compiler/aslrules.y
+++ b/sys/contrib/dev/acpica/compiler/aslrules.y
@@ -11,7 +11,7 @@ NoEcho('
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslstartup.c b/sys/contrib/dev/acpica/compiler/aslstartup.c
index 628a5c1ada2d..0da5eaa4d099 100644
--- a/sys/contrib/dev/acpica/compiler/aslstartup.c
+++ b/sys/contrib/dev/acpica/compiler/aslstartup.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslstubs.c b/sys/contrib/dev/acpica/compiler/aslstubs.c
index 50bda4b83fe1..f872b0f5f2e0 100644
--- a/sys/contrib/dev/acpica/compiler/aslstubs.c
+++ b/sys/contrib/dev/acpica/compiler/aslstubs.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslsupport.l b/sys/contrib/dev/acpica/compiler/aslsupport.l
index 74ac78d8c4ef..d9e609faee46 100644
--- a/sys/contrib/dev/acpica/compiler/aslsupport.l
+++ b/sys/contrib/dev/acpica/compiler/aslsupport.l
@@ -9,7 +9,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslsupport.y b/sys/contrib/dev/acpica/compiler/aslsupport.y
index 3bd09a55e704..7595c1065df6 100644
--- a/sys/contrib/dev/acpica/compiler/aslsupport.y
+++ b/sys/contrib/dev/acpica/compiler/aslsupport.y
@@ -9,7 +9,7 @@ NoEcho('
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/asltokens.y b/sys/contrib/dev/acpica/compiler/asltokens.y
index 50d6031e5ed0..0497ba9535ec 100644
--- a/sys/contrib/dev/acpica/compiler/asltokens.y
+++ b/sys/contrib/dev/acpica/compiler/asltokens.y
@@ -9,7 +9,7 @@ NoEcho('
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/asltransform.c b/sys/contrib/dev/acpica/compiler/asltransform.c
index c58f771354f1..f239ff0b11fe 100644
--- a/sys/contrib/dev/acpica/compiler/asltransform.c
+++ b/sys/contrib/dev/acpica/compiler/asltransform.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/asltree.c b/sys/contrib/dev/acpica/compiler/asltree.c
index 9237176c94b5..d8021dbbb765 100644
--- a/sys/contrib/dev/acpica/compiler/asltree.c
+++ b/sys/contrib/dev/acpica/compiler/asltree.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/asltypes.h b/sys/contrib/dev/acpica/compiler/asltypes.h
index 50234d71f0a7..36052302e9bf 100644
--- a/sys/contrib/dev/acpica/compiler/asltypes.h
+++ b/sys/contrib/dev/acpica/compiler/asltypes.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/asltypes.y b/sys/contrib/dev/acpica/compiler/asltypes.y
index 2c2669559585..3bfbae4f7b04 100644
--- a/sys/contrib/dev/acpica/compiler/asltypes.y
+++ b/sys/contrib/dev/acpica/compiler/asltypes.y
@@ -9,7 +9,7 @@ NoEcho('
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslutils.c b/sys/contrib/dev/acpica/compiler/aslutils.c
index 267ad8b77e13..69d0a2310a8d 100644
--- a/sys/contrib/dev/acpica/compiler/aslutils.c
+++ b/sys/contrib/dev/acpica/compiler/aslutils.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/asluuid.c b/sys/contrib/dev/acpica/compiler/asluuid.c
index 712a06fda951..a7e08380c67b 100644
--- a/sys/contrib/dev/acpica/compiler/asluuid.c
+++ b/sys/contrib/dev/acpica/compiler/asluuid.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/aslwalks.c b/sys/contrib/dev/acpica/compiler/aslwalks.c
index db2c9daa455e..c28177603823 100644
--- a/sys/contrib/dev/acpica/compiler/aslwalks.c
+++ b/sys/contrib/dev/acpica/compiler/aslwalks.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -197,6 +197,7 @@ AnMethodTypingWalkEnd (
void *Context)
{
UINT32 ThisOpBtype;
+ ACPI_PARSE_OBJECT *TargetMethodOp;
switch (Op->Asl.ParseOpcode)
@@ -227,12 +228,24 @@ AnMethodTypingWalkEnd (
if (Op->Asl.Child->Asl.Node &&
(Op->Asl.ParentMethod != Op->Asl.Child->Asl.Node->Op))
{
+ TargetMethodOp = Op->Asl.Child->Asl.Node->Op;
+
+ /* Break mutual-recursion loops during typing */
+ if (TargetMethodOp->Asl.CompileFlags & OP_VISITED)
+ {
+ break;
+ }
+
+ TargetMethodOp->Asl.CompileFlags |= OP_VISITED;
+
/* We must type the method here */
- TrWalkParseTree (Op->Asl.Child->Asl.Node->Op,
+ TrWalkParseTree (TargetMethodOp,
ASL_WALK_VISIT_UPWARD, NULL,
AnMethodTypingWalkEnd, NULL);
+ TargetMethodOp->Asl.CompileFlags &= ~OP_VISITED;
+
ThisOpBtype = AnGetBtype (Op->Asl.Child);
}
}
diff --git a/sys/contrib/dev/acpica/compiler/aslxref.c b/sys/contrib/dev/acpica/compiler/aslxref.c
index eb61b1d461cd..0f8c62262a0c 100644
--- a/sys/contrib/dev/acpica/compiler/aslxref.c
+++ b/sys/contrib/dev/acpica/compiler/aslxref.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -558,11 +558,23 @@ XfNamespaceLocateBegin (
Node = NextOp->Asl.Node;
+ /* Malformed tree: parent method has no namespace node */
+ if (!Node)
+ {
+ return_ACPI_STATUS (AE_OK);
+ }
+
/* Get Arg # */
RegisterNumber = Op->Asl.AmlOpcode - AML_ARG0; /* 0x68 through 0x6F */
MethodArgs = Node->MethodArgs;
+ /* Gracefully handle malformed trees where method args were not set up */
+ if (!MethodArgs)
+ {
+ return_ACPI_STATUS (AE_OK);
+ }
+
/* Mark this Arg as referenced */
MethodArgs[RegisterNumber].Flags |= ASL_ARG_REFERENCED;
diff --git a/sys/contrib/dev/acpica/compiler/aslxrefout.c b/sys/contrib/dev/acpica/compiler/aslxrefout.c
index 67e26b3e69de..86c66868b857 100644
--- a/sys/contrib/dev/acpica/compiler/aslxrefout.c
+++ b/sys/contrib/dev/acpica/compiler/aslxrefout.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/cvcompiler.c b/sys/contrib/dev/acpica/compiler/cvcompiler.c
index e42dfa8066ac..de8c523e5647 100644
--- a/sys/contrib/dev/acpica/compiler/cvcompiler.c
+++ b/sys/contrib/dev/acpica/compiler/cvcompiler.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/cvdisasm.c b/sys/contrib/dev/acpica/compiler/cvdisasm.c
index ebc93a0bd194..f4eac2861996 100644
--- a/sys/contrib/dev/acpica/compiler/cvdisasm.c
+++ b/sys/contrib/dev/acpica/compiler/cvdisasm.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/cvparser.c b/sys/contrib/dev/acpica/compiler/cvparser.c
index 724daa0dea67..db5595e47d3e 100644
--- a/sys/contrib/dev/acpica/compiler/cvparser.c
+++ b/sys/contrib/dev/acpica/compiler/cvparser.c
@@ -9,7 +9,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/dtcompile.c b/sys/contrib/dev/acpica/compiler/dtcompile.c
index 873baf397e47..e3447e28e0f0 100644
--- a/sys/contrib/dev/acpica/compiler/dtcompile.c
+++ b/sys/contrib/dev/acpica/compiler/dtcompile.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -363,18 +363,42 @@ DtInsertCompilerIds (
return;
}
- /* Walk to the Compiler fields at the end of the header */
+ /* Walk to the Compiler fields at the end of the header, with safety checks */
+
+ if (!FieldList)
+ {
+ DtError (ASL_WARNING, ASL_MSG_MALFORMED_HEADER, NULL, NULL);
+ return;
+ }
Next = FieldList;
for (i = 0; i < 7; i++)
{
+ if (!Next || !Next->Next)
+ {
+ /* Malformed/short header: cannot insert compiler IDs */
+ DtError (ASL_WARNING, ASL_MSG_MALFORMED_HEADER, FieldList, NULL);
+ return;
+ }
Next = Next->Next;
}
+ /* Ensure both Creator ID and Revision fields exist */
+ if (!Next || !Next->Next)
+ {
+ DtError (ASL_WARNING, ASL_MSG_MALFORMED_HEADER, FieldList, NULL);
+ return;
+ }
+
Next->Value = ASL_CREATOR_ID;
Next->Flags = DT_FIELD_NOT_ALLOCATED;
Next = Next->Next;
+ if (!Next)
+ {
+ DtError (ASL_WARNING, ASL_MSG_MALFORMED_HEADER, FieldList, NULL);
+ return;
+ }
Next->Value = VersionString;
Next->Flags = DT_FIELD_NOT_ALLOCATED;
}
diff --git a/sys/contrib/dev/acpica/compiler/dtcompiler.h b/sys/contrib/dev/acpica/compiler/dtcompiler.h
index 505bb6b40bed..6a47bd7b1691 100644
--- a/sys/contrib/dev/acpica/compiler/dtcompiler.h
+++ b/sys/contrib/dev/acpica/compiler/dtcompiler.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -610,6 +610,10 @@ DtCompileDrtm (
void **PFieldList);
ACPI_STATUS
+DtCompileDtpr (
+ void **PFieldList);
+
+ACPI_STATUS
DtCompileEinj (
void **PFieldList);
@@ -819,6 +823,7 @@ extern const unsigned char TemplateDbg2[];
extern const unsigned char TemplateDbgp[];
extern const unsigned char TemplateDmar[];
extern const unsigned char TemplateDrtm[];
+extern const unsigned char TemplateDtpr[];
extern const unsigned char TemplateEcdt[];
extern const unsigned char TemplateEinj[];
extern const unsigned char TemplateErdt[];
diff --git a/sys/contrib/dev/acpica/compiler/dtcompilerparser.l b/sys/contrib/dev/acpica/compiler/dtcompilerparser.l
index 322ee225a60d..492468867acd 100644
--- a/sys/contrib/dev/acpica/compiler/dtcompilerparser.l
+++ b/sys/contrib/dev/acpica/compiler/dtcompilerparser.l
@@ -9,7 +9,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/dtcompilerparser.y b/sys/contrib/dev/acpica/compiler/dtcompilerparser.y
index f160434e0959..4dab55c0b783 100644
--- a/sys/contrib/dev/acpica/compiler/dtcompilerparser.y
+++ b/sys/contrib/dev/acpica/compiler/dtcompilerparser.y
@@ -9,7 +9,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/dtexpress.c b/sys/contrib/dev/acpica/compiler/dtexpress.c
index 65f10aac9f00..0a503febb22d 100644
--- a/sys/contrib/dev/acpica/compiler/dtexpress.c
+++ b/sys/contrib/dev/acpica/compiler/dtexpress.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/dtfield.c b/sys/contrib/dev/acpica/compiler/dtfield.c
index ded7315aaa3f..106db4d04e58 100644
--- a/sys/contrib/dev/acpica/compiler/dtfield.c
+++ b/sys/contrib/dev/acpica/compiler/dtfield.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/dtio.c b/sys/contrib/dev/acpica/compiler/dtio.c
index 7bcf16b8f9d1..b0a830386834 100644
--- a/sys/contrib/dev/acpica/compiler/dtio.c
+++ b/sys/contrib/dev/acpica/compiler/dtio.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -422,6 +422,12 @@ DtParseLine (
End++;
}
+ /* No value characters present */
+ if (End <= Start)
+ {
+ return (AE_OK);
+ }
+
Length = ACPI_PTR_DIFF (End, Start);
TmpValue = UtLocalCalloc (Length + 1);
diff --git a/sys/contrib/dev/acpica/compiler/dtparser.l b/sys/contrib/dev/acpica/compiler/dtparser.l
index 90fc39d8c66a..b7574e77a6ad 100644
--- a/sys/contrib/dev/acpica/compiler/dtparser.l
+++ b/sys/contrib/dev/acpica/compiler/dtparser.l
@@ -9,7 +9,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/dtparser.y b/sys/contrib/dev/acpica/compiler/dtparser.y
index d6d584b2c6e9..9f6ad8b33d41 100644
--- a/sys/contrib/dev/acpica/compiler/dtparser.y
+++ b/sys/contrib/dev/acpica/compiler/dtparser.y
@@ -9,7 +9,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/dtsubtable.c b/sys/contrib/dev/acpica/compiler/dtsubtable.c
index 0c660b7ab8bb..82a7b0c8a14c 100644
--- a/sys/contrib/dev/acpica/compiler/dtsubtable.c
+++ b/sys/contrib/dev/acpica/compiler/dtsubtable.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -430,7 +430,12 @@ DtGetSubtableLength (
case ACPI_DMT_IORTMEM:
- Step = 10;
+ /*
+ * The ACPI_DMT_IORTMEM type is defined in AcpiDmTableInfoIortAcc.
+ * TODO: compute number of fields ("Step") directly from the array initialisation.
+ * This may require some refactoring of dmtbinfo2.c and acdiasasm.h
+ */
+ Step = 11;
break;
default:
diff --git a/sys/contrib/dev/acpica/compiler/dttable.c b/sys/contrib/dev/acpica/compiler/dttable.c
index effcf6d65e1c..6e0a0fedb0c0 100644
--- a/sys/contrib/dev/acpica/compiler/dttable.c
+++ b/sys/contrib/dev/acpica/compiler/dttable.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/dttable1.c b/sys/contrib/dev/acpica/compiler/dttable1.c
index a513ff9ed009..d82153d6a590 100644
--- a/sys/contrib/dev/acpica/compiler/dttable1.c
+++ b/sys/contrib/dev/acpica/compiler/dttable1.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -1728,6 +1728,124 @@ DtCompileDrtm (
/******************************************************************************
*
+ * FUNCTION: DtCompileDtpr
+ *
+ * PARAMETERS: List - Current field list pointer
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Compile DTPR.
+ *
+ *****************************************************************************/
+
+ACPI_STATUS
+DtCompileDtpr (
+ void **List)
+{
+ ACPI_STATUS Status;
+ DT_SUBTABLE *Subtable;
+ DT_SUBTABLE *ParentTable;
+ DT_FIELD **PFieldList = (DT_FIELD **) List;
+ ACPI_TABLE_DTPR *Dtpr;
+ ACPI_TPR_INSTANCE *TprInst;
+ UINT32 i, InsCnt, SrlCnt, TprCnt;
+
+
+ ParentTable = DtPeekSubtable ();
+
+ Status = DtCompileTable (PFieldList, AcpiDmTableInfoDtpr, &Subtable);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ DtInsertSubtable (ParentTable, Subtable);
+
+ Dtpr = ACPI_SUB_PTR (ACPI_TABLE_DTPR, Subtable->Buffer,
+ sizeof (ACPI_TABLE_HEADER));
+ if (!Dtpr)
+ {
+ AcpiOsPrintf ("DTPR buffer pointer is NULL\n");
+ return (AE_NULL_OBJECT);
+ }
+
+ InsCnt = Dtpr->InsCnt;
+
+ while (*PFieldList)
+ {
+ for (i = 0; i < InsCnt; i++)
+ {
+ Status = DtCompileTable (PFieldList, AcpiDmTableInfoDtprInstance,
+ &Subtable);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ TprInst = ACPI_CAST_PTR (ACPI_TPR_INSTANCE, Subtable->Buffer);
+ if (!TprInst)
+ {
+ AcpiOsPrintf ("Tpr Instance buffer pointer is NULL\n");
+ return (AE_NULL_OBJECT);
+ }
+
+ TprCnt = TprInst->TprCnt;
+ DtInsertSubtable (ParentTable, Subtable);
+ DtPushSubtable (Subtable);
+ ParentTable = DtPeekSubtable ();
+
+ while (*PFieldList && TprCnt)
+ {
+ Status = DtCompileTable (PFieldList, AcpiDmTableInfoDtprArr,
+ &Subtable);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ DtInsertSubtable (ParentTable, Subtable);
+ TprCnt--;
+ }
+
+ DtPopSubtable();
+ ParentTable = DtPeekSubtable ();
+ }
+
+ Status = DtCompileTable (PFieldList, AcpiDmTableInfoDtprSerializeReq0,
+ &Subtable);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ SrlCnt = *ACPI_CAST_PTR(UINT32, Subtable->Buffer);
+ DtInsertSubtable (ParentTable, Subtable);
+ DtPushSubtable (Subtable);
+ ParentTable = DtPeekSubtable ();
+
+ while (*PFieldList && SrlCnt)
+ {
+ Status = DtCompileTable (PFieldList, AcpiDmTableInfoDtprSerializeReq1,
+ &Subtable);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ DtInsertSubtable (ParentTable, Subtable);
+ SrlCnt--;
+ }
+
+
+ DtPopSubtable();
+ ParentTable = DtPeekSubtable ();
+ }
+
+ return Status;
+}
+
+/******************************************************************************
+ *
* FUNCTION: DtCompileEinj
*
* PARAMETERS: List - Current field list pointer
@@ -2984,6 +3102,19 @@ DtCompileIort (
IortRmr->RmrCount = RmrCount;
break;
+ case ACPI_IORT_NODE_IWB:
+
+ Status = DtCompileTable (PFieldList, AcpiDmTableInfoIort7,
+ &Subtable);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ DtInsertSubtable (ParentTable, Subtable);
+ NodeLength += Subtable->Length;
+ break;
+
default:
DtFatal (ASL_MSG_UNKNOWN_SUBTABLE, SubtableStart, "IORT");
diff --git a/sys/contrib/dev/acpica/compiler/dttable2.c b/sys/contrib/dev/acpica/compiler/dttable2.c
index 43484490ff3e..e5ecb25332b9 100644
--- a/sys/contrib/dev/acpica/compiler/dttable2.c
+++ b/sys/contrib/dev/acpica/compiler/dttable2.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -439,6 +439,21 @@ DtCompileMadt (
InfoTable = AcpiDmTableInfoMadt27;
break;
+ case ACPI_MADT_TYPE_GICV5_IRS:
+
+ InfoTable = AcpiDmTableInfoMadt28;
+ break;
+
+ case ACPI_MADT_TYPE_GICV5_ITS:
+
+ InfoTable = AcpiDmTableInfoMadt29;
+ break;
+
+ case ACPI_MADT_TYPE_GICV5_ITS_TRANSLATE:
+
+ InfoTable = AcpiDmTableInfoMadt30;
+ break;
+
default:
if (MadtHeader->Type >= ACPI_MADT_TYPE_OEM_RESERVED)
diff --git a/sys/contrib/dev/acpica/compiler/dttemplate.c b/sys/contrib/dev/acpica/compiler/dttemplate.c
index d7140712d4e6..57d64cba27fa 100644
--- a/sys/contrib/dev/acpica/compiler/dttemplate.c
+++ b/sys/contrib/dev/acpica/compiler/dttemplate.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/dttemplate.h b/sys/contrib/dev/acpica/compiler/dttemplate.h
index 88bc38f25c39..460f3a54afe5 100644
--- a/sys/contrib/dev/acpica/compiler/dttemplate.h
+++ b/sys/contrib/dev/acpica/compiler/dttemplate.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -643,6 +643,23 @@ const unsigned char TemplateEcdt[] =
0x09,0x00 /* 00000040 ".." */
};
+const unsigned char TemplateDtpr[] =
+{
+ 0x44,0x54,0x50,0x52,0x68,0x00,0x00,0x00, /* 00000000 "DTPRh..." */
+ 0x01,0x0B,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 ".#INTEL." */
+ 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */
+ 0x00,0x00,0x00,0x01,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */
+ 0x04,0x04,0x25,0x20,0x00,0x00,0x00,0x00, /* 00000020 "........" */
+ 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000028 "........" */
+ 0x02,0x00,0x00,0x00,0x30,0xB0,0xAA,0xFF, /* 00000030 "....0..." */
+ 0xFF,0x1F,0x00,0x00,0x38,0xB0,0xAA,0xFF, /* 00000038 "....8..." */
+ 0xFF,0x1F,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000040 "........" */
+ 0x02,0x00,0x00,0x00,0x30,0xB0,0xBB,0xFF, /* 00000048 "....0..." */
+ 0xFF,0x1F,0x00,0x00,0x38,0xB0,0xBB,0xFF, /* 00000050 "....8..." */
+ 0xFF,0x1F,0x00,0x00,0x01,0x00,0x00,0x00, /* 00000058 "........" */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 /* 00000060 "........" */
+};
+
const unsigned char TemplateEinj[] =
{
0x45,0x49,0x4E,0x4A,0x30,0x01,0x00,0x00, /* 00000000 "EINJ0..." */
@@ -1188,11 +1205,11 @@ const unsigned char TemplateHpet[] =
const unsigned char TemplateIort[] =
{
- 0x49,0x4F,0x52,0x54,0x3C,0x02,0x00,0x00, /* 00000000 "IORT<..." */
- 0x05,0xCB,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */
+ 0x49,0x4F,0x52,0x54,0x78,0x02,0x00,0x00, /* 00000000 "IORTx..." */
+ 0x05,0x85,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */
0x54,0x65,0x6D,0x70,0x6C,0x61,0x74,0x65, /* 00000010 "Template" */
0x00,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */
- 0x17,0x12,0x21,0x20,0x07,0x00,0x00,0x00, /* 00000020 "..! ...." */
+ 0x07,0x08,0x25,0x20,0x08,0x00,0x00,0x00, /* 00000020 "..% ...." */
0x34,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000028 "4......." */
0x49,0x4F,0x52,0x54,0x00,0x18,0x00,0x01, /* 00000030 "IORT...." */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000038 "........" */
@@ -1204,10 +1221,10 @@ const unsigned char TemplateIort[] =
0x00,0x5C,0x5F,0x53,0x42,0x2E,0x50,0x43, /* 00000068 ".\_SB.PC" */
0x49,0x30,0x2E,0x44,0x45,0x56,0x30,0x00, /* 00000070 "I0.DEV0." */
0x49,0x4F,0x52,0x54,0x3C,0x02,0x00,0x00, /* 00000078 "IORT<..." */
- 0x03,0xF1,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000080 "..INTEL " */
+ 0x05,0xCB,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000080 "..INTEL " */
0x54,0x65,0x6D,0x70,0x6C,0x61,0x74,0x65, /* 00000088 "Template" */
0x00,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000090 "....INTL" */
- 0x05,0x01,0x21,0x20,0x07,0x00,0x00,0x00, /* 00000098 "..! ...." */
+ 0x17,0x12,0x21,0x20,0x07,0x00,0x00,0x00, /* 00000098 "..! ...." */
0x34,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000A0 "4......." */
0x49,0x4F,0x52,0x54,0x00,0x18,0x00,0x01, /* 000000A8 "IORT...." */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000B0 "........" */
@@ -1259,7 +1276,14 @@ const unsigned char TemplateIort[] =
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000220 "........" */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000228 "........" */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000230 "........" */
- 0x00,0x00,0x00,0x00 /* 00000238 "...." */
+ 0x00,0x00,0x00,0x00,0x07,0x3C,0x00,0x01, /* 00000238 ".....<.." */
+ 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, /* 00000240 "........" */
+ 0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x2F, /* 00000248 "(....../" */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x5C,0x5F, /* 00000250 "......\_" */
+ 0x53,0x42,0x5F,0x2E,0x49,0x57,0x42,0x30, /* 00000258 "SB_.IWB0" */
+ 0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00, /* 00000260 "........" */
+ 0x00,0x40,0x00,0x00,0x00,0x30,0x00,0x00, /* 00000268 ".@...0.." */
+ 0x00,0x01,0x00,0x00,0x00 /* 00000270 "....." */
};
const unsigned char TemplateIovt[] =
@@ -1387,15 +1411,15 @@ const unsigned char TemplateLpit[] =
0x00,0x00,0x00,0x00 /* 00000090 "...." */
};
-/* MADT with ACPI 6.0 subtables */
+/* MADT with ACPI 6.7 subtables */
const unsigned char TemplateMadt[] =
{
- 0x41,0x50,0x49,0x43,0x62,0x02,0x00,0x00, /* 00000000 "APICb..." */
- 0x07,0x44,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 ".DINTEL " */
+ 0x41,0x50,0x49,0x43,0xAA,0x02,0x00,0x00, /* 00000000 "APIC...." */
+ 0x07,0x5F,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "._INTEL " */
0x54,0x65,0x6D,0x70,0x6C,0x61,0x74,0x65, /* 00000010 "Template" */
0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */
- 0x28,0x06,0x23,0x20,0x00,0x00,0x00,0x00, /* 00000020 "(.# ...." */
+ 0x07,0x08,0x25,0x20,0x00,0x00,0x00,0x00, /* 00000020 "..% ...." */
0x01,0x00,0x00,0x00,0x00,0x08,0x00,0x00, /* 00000028 "........" */
0x01,0x00,0x00,0x00,0x01,0x0C,0x01,0x00, /* 00000030 "........" */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000038 "........" */
@@ -1467,7 +1491,16 @@ const unsigned char TemplateMadt[] =
0x00,0x00,0x60,0x00,0x00,0x00,0x00,0x00, /* 00000248 "..`....." */
0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x00, /* 00000250 "....`..." */
0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000258 "........" */
- 0x00,0x00 /* 00000260 ".." */
+ 0x00,0x00,0x1D,0x10,0x00,0x00,0x00,0x00, /* 00000260 "........" */
+ 0x00,0x00,0x00,0x00,0x12,0x2F,0x00,0x00, /* 00000268 "...../.." */
+ 0x00,0x00,0x1E,0x18,0x00,0x00,0x00,0x00, /* 00000270 "........" */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000278 "........" */
+ 0x00,0x00,0x00,0x00,0x13,0x2F,0x00,0x00, /* 00000280 "...../.." */
+ 0x00,0x00,0x1C,0x20,0x05,0x00,0x00,0x00, /* 00000288 "... ...." */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000290 "........" */
+ 0x00,0x00,0x00,0x00,0x1A,0x2F,0x00,0x00, /* 00000298 "...../.." */
+ 0x00,0x00,0x00,0x00,0x1B,0x2F,0x00,0x00, /* 000002A0 "...../.." */
+ 0x00,0x00 /* 000002A8 ".." */
};
const unsigned char TemplateMcfg[] =
diff --git a/sys/contrib/dev/acpica/compiler/dtutils.c b/sys/contrib/dev/acpica/compiler/dtutils.c
index f3b9fa856dd6..ff3b1b6e9453 100644
--- a/sys/contrib/dev/acpica/compiler/dtutils.c
+++ b/sys/contrib/dev/acpica/compiler/dtutils.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/preprocess.h b/sys/contrib/dev/acpica/compiler/preprocess.h
index 26a11f573402..8e3a602027b8 100644
--- a/sys/contrib/dev/acpica/compiler/preprocess.h
+++ b/sys/contrib/dev/acpica/compiler/preprocess.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/prexpress.c b/sys/contrib/dev/acpica/compiler/prexpress.c
index b2e7b785c5e9..ec430eda1b11 100644
--- a/sys/contrib/dev/acpica/compiler/prexpress.c
+++ b/sys/contrib/dev/acpica/compiler/prexpress.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/prmacros.c b/sys/contrib/dev/acpica/compiler/prmacros.c
index 6d2acf52b980..350839192c42 100644
--- a/sys/contrib/dev/acpica/compiler/prmacros.c
+++ b/sys/contrib/dev/acpica/compiler/prmacros.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/prparser.l b/sys/contrib/dev/acpica/compiler/prparser.l
index fe0495121911..d286cb84da7b 100644
--- a/sys/contrib/dev/acpica/compiler/prparser.l
+++ b/sys/contrib/dev/acpica/compiler/prparser.l
@@ -9,7 +9,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/prparser.y b/sys/contrib/dev/acpica/compiler/prparser.y
index 47edb20dcba8..7a724e9ed55e 100644
--- a/sys/contrib/dev/acpica/compiler/prparser.y
+++ b/sys/contrib/dev/acpica/compiler/prparser.y
@@ -9,7 +9,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/prscan.c b/sys/contrib/dev/acpica/compiler/prscan.c
index 81b703cfb081..59ef7cc73bf0 100644
--- a/sys/contrib/dev/acpica/compiler/prscan.c
+++ b/sys/contrib/dev/acpica/compiler/prscan.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/compiler/prutils.c b/sys/contrib/dev/acpica/compiler/prutils.c
index 902baed833c8..2bf700594ae3 100644
--- a/sys/contrib/dev/acpica/compiler/prutils.c
+++ b/sys/contrib/dev/acpica/compiler/prutils.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/debugger/dbcmds.c b/sys/contrib/dev/acpica/components/debugger/dbcmds.c
index 17ec5f342618..8b335c0c6ad2 100644
--- a/sys/contrib/dev/acpica/components/debugger/dbcmds.c
+++ b/sys/contrib/dev/acpica/components/debugger/dbcmds.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/debugger/dbconvert.c b/sys/contrib/dev/acpica/components/debugger/dbconvert.c
index ed464e25bdbe..0a7cc420c07d 100644
--- a/sys/contrib/dev/acpica/components/debugger/dbconvert.c
+++ b/sys/contrib/dev/acpica/components/debugger/dbconvert.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/debugger/dbdisply.c b/sys/contrib/dev/acpica/components/debugger/dbdisply.c
index c57a19d0dbdb..c2812a1d171e 100644
--- a/sys/contrib/dev/acpica/components/debugger/dbdisply.c
+++ b/sys/contrib/dev/acpica/components/debugger/dbdisply.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/debugger/dbexec.c b/sys/contrib/dev/acpica/components/debugger/dbexec.c
index 38c7496ebba1..c1f4e8a52f24 100644
--- a/sys/contrib/dev/acpica/components/debugger/dbexec.c
+++ b/sys/contrib/dev/acpica/components/debugger/dbexec.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/debugger/dbfileio.c b/sys/contrib/dev/acpica/components/debugger/dbfileio.c
index b006ac9d330b..d575f4929d30 100644
--- a/sys/contrib/dev/acpica/components/debugger/dbfileio.c
+++ b/sys/contrib/dev/acpica/components/debugger/dbfileio.c
@@ -9,7 +9,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/debugger/dbhistry.c b/sys/contrib/dev/acpica/components/debugger/dbhistry.c
index 45d44d11f315..5a7ecbaa51b8 100644
--- a/sys/contrib/dev/acpica/components/debugger/dbhistry.c
+++ b/sys/contrib/dev/acpica/components/debugger/dbhistry.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/debugger/dbinput.c b/sys/contrib/dev/acpica/components/debugger/dbinput.c
index e38364448885..03fa49a63428 100644
--- a/sys/contrib/dev/acpica/components/debugger/dbinput.c
+++ b/sys/contrib/dev/acpica/components/debugger/dbinput.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/debugger/dbmethod.c b/sys/contrib/dev/acpica/components/debugger/dbmethod.c
index 27e572d5ad17..8f2586784fc4 100644
--- a/sys/contrib/dev/acpica/components/debugger/dbmethod.c
+++ b/sys/contrib/dev/acpica/components/debugger/dbmethod.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/debugger/dbnames.c b/sys/contrib/dev/acpica/components/debugger/dbnames.c
index fc6a26fe9cdc..64abc3a55172 100644
--- a/sys/contrib/dev/acpica/components/debugger/dbnames.c
+++ b/sys/contrib/dev/acpica/components/debugger/dbnames.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/debugger/dbobject.c b/sys/contrib/dev/acpica/components/debugger/dbobject.c
index 0033b61ccab8..5f8d511dca95 100644
--- a/sys/contrib/dev/acpica/components/debugger/dbobject.c
+++ b/sys/contrib/dev/acpica/components/debugger/dbobject.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/debugger/dbstats.c b/sys/contrib/dev/acpica/components/debugger/dbstats.c
index 76295cadd337..71ec9b23926e 100644
--- a/sys/contrib/dev/acpica/components/debugger/dbstats.c
+++ b/sys/contrib/dev/acpica/components/debugger/dbstats.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/debugger/dbtest.c b/sys/contrib/dev/acpica/components/debugger/dbtest.c
index 4e0eb486c35b..eda8013762b0 100644
--- a/sys/contrib/dev/acpica/components/debugger/dbtest.c
+++ b/sys/contrib/dev/acpica/components/debugger/dbtest.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/debugger/dbutils.c b/sys/contrib/dev/acpica/components/debugger/dbutils.c
index 4a39f9aca9e0..1382a4bcb605 100755
--- a/sys/contrib/dev/acpica/components/debugger/dbutils.c
+++ b/sys/contrib/dev/acpica/components/debugger/dbutils.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/debugger/dbxface.c b/sys/contrib/dev/acpica/components/debugger/dbxface.c
index 2150abc16100..885c633f01f6 100644
--- a/sys/contrib/dev/acpica/components/debugger/dbxface.c
+++ b/sys/contrib/dev/acpica/components/debugger/dbxface.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/disassembler/dmbuffer.c b/sys/contrib/dev/acpica/components/disassembler/dmbuffer.c
index d9e2273712e5..0b008559dbe1 100644
--- a/sys/contrib/dev/acpica/components/disassembler/dmbuffer.c
+++ b/sys/contrib/dev/acpica/components/disassembler/dmbuffer.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/disassembler/dmcstyle.c b/sys/contrib/dev/acpica/components/disassembler/dmcstyle.c
index ce3aa09084df..89ecc7a39c0f 100644
--- a/sys/contrib/dev/acpica/components/disassembler/dmcstyle.c
+++ b/sys/contrib/dev/acpica/components/disassembler/dmcstyle.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/disassembler/dmdeferred.c b/sys/contrib/dev/acpica/components/disassembler/dmdeferred.c
index 3826f194d6fd..b0cacb4d873f 100644
--- a/sys/contrib/dev/acpica/components/disassembler/dmdeferred.c
+++ b/sys/contrib/dev/acpica/components/disassembler/dmdeferred.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/disassembler/dmnames.c b/sys/contrib/dev/acpica/components/disassembler/dmnames.c
index 447618b5bc52..0f5df03dbf41 100644
--- a/sys/contrib/dev/acpica/components/disassembler/dmnames.c
+++ b/sys/contrib/dev/acpica/components/disassembler/dmnames.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/disassembler/dmopcode.c b/sys/contrib/dev/acpica/components/disassembler/dmopcode.c
index 1cb1c81d74eb..73e9d168d7c1 100644
--- a/sys/contrib/dev/acpica/components/disassembler/dmopcode.c
+++ b/sys/contrib/dev/acpica/components/disassembler/dmopcode.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -797,6 +797,7 @@ AcpiDmDisassembleOneOp (
UINT32 Offset;
UINT32 Length;
ACPI_PARSE_OBJECT *Child;
+ ACPI_PARSE_OBJECT *MethodCallOp;
ACPI_STATUS Status;
UINT8 *Aml;
const AH_DEVICE_ID *IdInfo;
@@ -986,6 +987,13 @@ AcpiDmDisassembleOneOp (
case AML_INT_NAMEPATH_OP:
AcpiDmNamestring (Op->Common.Value.Name);
+ /* If this namepath is a Package element, emit a separating comma */
+ if ((Op->Common.Parent) &&
+ ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
+ (Op->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP)))
+ {
+ AcpiOsPrintf (", ");
+ }
break;
case AML_INT_NAMEDFIELD_OP:
@@ -1086,10 +1094,19 @@ AcpiDmDisassembleOneOp (
case AML_INT_METHODCALL_OP:
+ MethodCallOp = Op;
Op = AcpiPsGetDepthNext (NULL, Op);
Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
AcpiDmNamestring (Op->Common.Value.Name);
+
+ /* If the method name is a Package element, emit a separating comma */
+ if ((MethodCallOp->Common.Parent) &&
+ ((MethodCallOp->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
+ (MethodCallOp->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP)))
+ {
+ AcpiOsPrintf (", ");
+ }
break;
case AML_WHILE_OP:
diff --git a/sys/contrib/dev/acpica/components/disassembler/dmresrc.c b/sys/contrib/dev/acpica/components/disassembler/dmresrc.c
index e5a859ed47b7..a91b2c0ee00b 100644
--- a/sys/contrib/dev/acpica/components/disassembler/dmresrc.c
+++ b/sys/contrib/dev/acpica/components/disassembler/dmresrc.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -536,10 +536,31 @@ AcpiDmIsResourceTemplate (
return (AE_TYPE);
}
+ /*
+ * Check if this op was allocated from the extended parse object cache.
+ * Only extended ops (NAMED_OBJECT, DEFERRED, BYTELIST) have the
+ * Named.Data and Named.Length fields. Generic ops would overflow.
+ */
+ if (NextOp->Common.Flags == ACPI_PARSEOP_GENERIC)
+ {
+ return (AE_TYPE);
+ }
+
Aml = NextOp->Named.Data;
BufferLength = NextOp->Common.Value.Size;
/*
+ * Validate BufferLength against Named.Length to prevent reading
+ * beyond the actual data. Named.Length is computed during parsing
+ * and represents the actual byte count, while Value.Size comes
+ * from the AML and can be manipulated by malformed AML.
+ */
+ if (BufferLength > NextOp->Named.Length)
+ {
+ return (AE_TYPE);
+ }
+
+ /*
* Any buffer smaller than one byte cannot possibly be a resource
* template. Two bytes could possibly be a "NULL" resource template
* with a lone end tag descriptor (as generated via
diff --git a/sys/contrib/dev/acpica/components/disassembler/dmresrcl.c b/sys/contrib/dev/acpica/components/disassembler/dmresrcl.c
index b50766bcdf20..f72b96f4a6fa 100644
--- a/sys/contrib/dev/acpica/components/disassembler/dmresrcl.c
+++ b/sys/contrib/dev/acpica/components/disassembler/dmresrcl.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/disassembler/dmresrcl2.c b/sys/contrib/dev/acpica/components/disassembler/dmresrcl2.c
index 551cf8178d94..0ccd03018d73 100644
--- a/sys/contrib/dev/acpica/components/disassembler/dmresrcl2.c
+++ b/sys/contrib/dev/acpica/components/disassembler/dmresrcl2.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/disassembler/dmresrcs.c b/sys/contrib/dev/acpica/components/disassembler/dmresrcs.c
index 1398462cecfc..c601c357c471 100644
--- a/sys/contrib/dev/acpica/components/disassembler/dmresrcs.c
+++ b/sys/contrib/dev/acpica/components/disassembler/dmresrcs.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/disassembler/dmutils.c b/sys/contrib/dev/acpica/components/disassembler/dmutils.c
index 41e26ee4b755..1c674769348a 100644
--- a/sys/contrib/dev/acpica/components/disassembler/dmutils.c
+++ b/sys/contrib/dev/acpica/components/disassembler/dmutils.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/disassembler/dmwalk.c b/sys/contrib/dev/acpica/components/disassembler/dmwalk.c
index 36f6def2bba5..fda26ecb05b1 100644
--- a/sys/contrib/dev/acpica/components/disassembler/dmwalk.c
+++ b/sys/contrib/dev/acpica/components/disassembler/dmwalk.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -305,13 +305,6 @@ AcpiDmWalkParseTree (
}
}
- /* Terminate walk at start op */
-
- if (Op == StartOp)
- {
- break;
- }
-
/* No more children, re-visit this node */
if (!NodePreviouslyVisited)
@@ -320,6 +313,13 @@ AcpiDmWalkParseTree (
continue;
}
+ /* Terminate walk at start op */
+
+ if (Op == StartOp)
+ {
+ break;
+ }
+
/* No more children, visit peers */
if (Op->Common.Next)
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dsargs.c b/sys/contrib/dev/acpica/components/dispatcher/dsargs.c
index 4a60cde8a15a..e44ad78496dd 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dsargs.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dsargs.c
@@ -9,7 +9,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dscontrol.c b/sys/contrib/dev/acpica/components/dispatcher/dscontrol.c
index fcf10cf4e856..621655933195 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dscontrol.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dscontrol.c
@@ -9,7 +9,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dsdebug.c b/sys/contrib/dev/acpica/components/dispatcher/dsdebug.c
index feb7f58a95de..eba73f94896f 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dsdebug.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dsdebug.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dsfield.c b/sys/contrib/dev/acpica/components/dispatcher/dsfield.c
index baa6a2eef262..7972eb03efbb 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dsfield.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dsfield.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dsinit.c b/sys/contrib/dev/acpica/components/dispatcher/dsinit.c
index bcf2d4f112c8..eecb4601137d 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dsinit.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dsinit.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dsmethod.c b/sys/contrib/dev/acpica/components/dispatcher/dsmethod.c
index becdb95f8b83..bc7b559a0f3d 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dsmethod.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dsmethod.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -901,6 +901,8 @@ AcpiDsTerminateControlMethod (
ACPI_OPERAND_OBJECT *MethodDesc,
ACPI_WALK_STATE *WalkState)
{
+ UINT32 i;
+ ACPI_NAMESPACE_NODE *RefNode;
ACPI_FUNCTION_TRACE_PTR (DsTerminateControlMethod, WalkState);
@@ -914,6 +916,45 @@ AcpiDsTerminateControlMethod (
if (WalkState)
{
+ /*
+ * Check if the return value is a RefOf reference to a method local
+ * or argument. If so, clear the reference to avoid use-after-free
+ * when the walk state is deleted.
+ */
+ if (WalkState->ReturnDesc &&
+ (WalkState->ReturnDesc->Common.Type == ACPI_TYPE_LOCAL_REFERENCE) &&
+ (WalkState->ReturnDesc->Reference.Class == ACPI_REFCLASS_REFOF))
+ {
+ RefNode = WalkState->ReturnDesc->Reference.Object;
+ if (RefNode)
+ {
+ /* Check against method locals */
+ for (i = 0; i < ACPI_METHOD_NUM_LOCALS; i++)
+ {
+ if (RefNode == &WalkState->LocalVariables[i])
+ {
+ AcpiUtRemoveReference (WalkState->ReturnDesc);
+ WalkState->ReturnDesc = NULL;
+ break;
+ }
+ }
+
+ /* Check against method arguments if not already cleared */
+ if (WalkState->ReturnDesc)
+ {
+ for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++)
+ {
+ if (RefNode == &WalkState->Arguments[i])
+ {
+ AcpiUtRemoveReference (WalkState->ReturnDesc);
+ WalkState->ReturnDesc = NULL;
+ break;
+ }
+ }
+ }
+ }
+ }
+
/* Delete all arguments and locals */
AcpiDsMethodDataDeleteAll (WalkState);
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dsmthdat.c b/sys/contrib/dev/acpica/components/dispatcher/dsmthdat.c
index 2c45e8c91f57..8f401774e631 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dsmthdat.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dsmthdat.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dsobject.c b/sys/contrib/dev/acpica/components/dispatcher/dsobject.c
index cd9921e59261..cc233ad59acc 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dsobject.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dsobject.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dsopcode.c b/sys/contrib/dev/acpica/components/dispatcher/dsopcode.c
index 23c7065bec5a..7c47bab397da 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dsopcode.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dsopcode.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dspkginit.c b/sys/contrib/dev/acpica/components/dispatcher/dspkginit.c
index 6365ab4b0f20..8e37e9384c4a 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dspkginit.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dspkginit.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dsutils.c b/sys/contrib/dev/acpica/components/dispatcher/dsutils.c
index 04b65326b51c..4105850932a7 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dsutils.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dsutils.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dswexec.c b/sys/contrib/dev/acpica/components/dispatcher/dswexec.c
index 1e287fae9977..3243280ae428 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dswexec.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dswexec.c
@@ -9,7 +9,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dswload.c b/sys/contrib/dev/acpica/components/dispatcher/dswload.c
index 8c9969de14f7..5a0caaaf1854 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dswload.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dswload.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dswload2.c b/sys/contrib/dev/acpica/components/dispatcher/dswload2.c
index 8ef7ff4090d1..33572fd966e8 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dswload2.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dswload2.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dswscope.c b/sys/contrib/dev/acpica/components/dispatcher/dswscope.c
index faf08bcfb399..f5a7ded02bc6 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dswscope.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dswscope.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dswstate.c b/sys/contrib/dev/acpica/components/dispatcher/dswstate.c
index f353951961b2..cfd55276391d 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dswstate.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dswstate.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/events/evevent.c b/sys/contrib/dev/acpica/components/events/evevent.c
index da5e633e5909..b8e23ec86982 100644
--- a/sys/contrib/dev/acpica/components/events/evevent.c
+++ b/sys/contrib/dev/acpica/components/events/evevent.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/events/evglock.c b/sys/contrib/dev/acpica/components/events/evglock.c
index 395ca14fb315..bd9a414359ae 100644
--- a/sys/contrib/dev/acpica/components/events/evglock.c
+++ b/sys/contrib/dev/acpica/components/events/evglock.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/events/evgpe.c b/sys/contrib/dev/acpica/components/events/evgpe.c
index 2ce159c46be2..075e6230cb05 100644
--- a/sys/contrib/dev/acpica/components/events/evgpe.c
+++ b/sys/contrib/dev/acpica/components/events/evgpe.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/events/evgpeblk.c b/sys/contrib/dev/acpica/components/events/evgpeblk.c
index d30f31c641a1..9eff36bc46e0 100644
--- a/sys/contrib/dev/acpica/components/events/evgpeblk.c
+++ b/sys/contrib/dev/acpica/components/events/evgpeblk.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/events/evgpeinit.c b/sys/contrib/dev/acpica/components/events/evgpeinit.c
index 0ae8bb700369..ab7348807105 100644
--- a/sys/contrib/dev/acpica/components/events/evgpeinit.c
+++ b/sys/contrib/dev/acpica/components/events/evgpeinit.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/events/evgpeutil.c b/sys/contrib/dev/acpica/components/events/evgpeutil.c
index 0dc2fdf01b52..841112817035 100644
--- a/sys/contrib/dev/acpica/components/events/evgpeutil.c
+++ b/sys/contrib/dev/acpica/components/events/evgpeutil.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/events/evhandler.c b/sys/contrib/dev/acpica/components/events/evhandler.c
index 9c69d69b524a..8f29e830faa8 100644
--- a/sys/contrib/dev/acpica/components/events/evhandler.c
+++ b/sys/contrib/dev/acpica/components/events/evhandler.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -290,6 +290,13 @@ AcpiEvHasDefaultHandler (
while (HandlerObj)
{
+ /* Validate handler object type before accessing fields */
+
+ if (HandlerObj->Common.Type != ACPI_TYPE_LOCAL_ADDRESS_HANDLER)
+ {
+ break;
+ }
+
if (HandlerObj->AddressSpace.SpaceId == SpaceId)
{
if (HandlerObj->AddressSpace.HandlerFlags &
@@ -460,6 +467,11 @@ AcpiEvFindRegionHandler (
while (HandlerObj)
{
+ if (HandlerObj->Common.Type != ACPI_TYPE_LOCAL_ADDRESS_HANDLER)
+ {
+ break;
+ }
+
/* Same SpaceId indicates a handler is installed */
if (HandlerObj->AddressSpace.SpaceId == SpaceId)
diff --git a/sys/contrib/dev/acpica/components/events/evmisc.c b/sys/contrib/dev/acpica/components/events/evmisc.c
index 1b8688dd872d..13b2963ac04d 100644
--- a/sys/contrib/dev/acpica/components/events/evmisc.c
+++ b/sys/contrib/dev/acpica/components/events/evmisc.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/events/evregion.c b/sys/contrib/dev/acpica/components/events/evregion.c
index 23f9ad00bc62..01c49b86f5d6 100644
--- a/sys/contrib/dev/acpica/components/events/evregion.c
+++ b/sys/contrib/dev/acpica/components/events/evregion.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/events/evrgnini.c b/sys/contrib/dev/acpica/components/events/evrgnini.c
index 1f16655195e1..40943bb0de4b 100644
--- a/sys/contrib/dev/acpica/components/events/evrgnini.c
+++ b/sys/contrib/dev/acpica/components/events/evrgnini.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/events/evsci.c b/sys/contrib/dev/acpica/components/events/evsci.c
index cd1dc4da6317..156b19d9abdf 100644
--- a/sys/contrib/dev/acpica/components/events/evsci.c
+++ b/sys/contrib/dev/acpica/components/events/evsci.c
@@ -9,7 +9,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/events/evxface.c b/sys/contrib/dev/acpica/components/events/evxface.c
index 54634c61e517..fc4ecaeb1e67 100644
--- a/sys/contrib/dev/acpica/components/events/evxface.c
+++ b/sys/contrib/dev/acpica/components/events/evxface.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/events/evxfevnt.c b/sys/contrib/dev/acpica/components/events/evxfevnt.c
index 60837084e86f..0eba3a5028f1 100644
--- a/sys/contrib/dev/acpica/components/events/evxfevnt.c
+++ b/sys/contrib/dev/acpica/components/events/evxfevnt.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/events/evxfgpe.c b/sys/contrib/dev/acpica/components/events/evxfgpe.c
index 1ffcff259a2b..1b99879a7fbc 100644
--- a/sys/contrib/dev/acpica/components/events/evxfgpe.c
+++ b/sys/contrib/dev/acpica/components/events/evxfgpe.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/events/evxfregn.c b/sys/contrib/dev/acpica/components/events/evxfregn.c
index bbdf4352b415..706b13f2b813 100644
--- a/sys/contrib/dev/acpica/components/events/evxfregn.c
+++ b/sys/contrib/dev/acpica/components/events/evxfregn.c
@@ -9,7 +9,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/executer/exconcat.c b/sys/contrib/dev/acpica/components/executer/exconcat.c
index 060dbf946d87..a03d3c1c6515 100644
--- a/sys/contrib/dev/acpica/components/executer/exconcat.c
+++ b/sys/contrib/dev/acpica/components/executer/exconcat.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/executer/exconfig.c b/sys/contrib/dev/acpica/components/executer/exconfig.c
index 6f3f8d24baca..f73863e8d744 100644
--- a/sys/contrib/dev/acpica/components/executer/exconfig.c
+++ b/sys/contrib/dev/acpica/components/executer/exconfig.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -247,6 +247,8 @@ AcpiExLoadTableOp (
ACPI_OPERAND_OBJECT *ReturnObj;
ACPI_OPERAND_OBJECT *DdbHandle;
UINT32 TableIndex;
+ char OemId[ACPI_OEM_ID_SIZE + 1];
+ char OemTableId[ACPI_OEM_TABLE_ID_SIZE + 1];
ACPI_FUNCTION_TRACE (ExLoadTableOp);
@@ -262,13 +264,34 @@ AcpiExLoadTableOp (
*ReturnDesc = ReturnObj;
+ /*
+ * Validate OEM ID and OEM Table ID string lengths.
+ * AcpiTbFindTable expects strings that can safely read
+ * ACPI_OEM_ID_SIZE and ACPI_OEM_TABLE_ID_SIZE bytes.
+ */
+ if ((Operand[1]->String.Length > ACPI_OEM_ID_SIZE) ||
+ (Operand[2]->String.Length > ACPI_OEM_TABLE_ID_SIZE))
+ {
+ return_ACPI_STATUS (AE_AML_STRING_LIMIT);
+ }
+
+ /*
+ * Copy OEM strings to local buffers with guaranteed null-termination.
+ * This prevents heap-buffer-overflow when AcpiTbFindTable reads
+ * ACPI_OEM_ID_SIZE/ACPI_OEM_TABLE_ID_SIZE bytes.
+ */
+ memcpy (OemId, Operand[1]->String.Pointer, Operand[1]->String.Length);
+ OemId[Operand[1]->String.Length] = 0;
+ memcpy (OemTableId, Operand[2]->String.Pointer, Operand[2]->String.Length);
+ OemTableId[Operand[2]->String.Length] = 0;
+
/* Find the ACPI table in the RSDT/XSDT */
AcpiExExitInterpreter ();
Status = AcpiTbFindTable (
Operand[0]->String.Pointer,
- Operand[1]->String.Pointer,
- Operand[2]->String.Pointer, &TableIndex);
+ OemId,
+ OemTableId, &TableIndex);
AcpiExEnterInterpreter ();
if (ACPI_FAILURE (Status))
{
diff --git a/sys/contrib/dev/acpica/components/executer/exconvrt.c b/sys/contrib/dev/acpica/components/executer/exconvrt.c
index 9c091864d7ef..82397b606582 100644
--- a/sys/contrib/dev/acpica/components/executer/exconvrt.c
+++ b/sys/contrib/dev/acpica/components/executer/exconvrt.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/executer/excreate.c b/sys/contrib/dev/acpica/components/executer/excreate.c
index 75f1d631d110..b1b6d3509dd0 100644
--- a/sys/contrib/dev/acpica/components/executer/excreate.c
+++ b/sys/contrib/dev/acpica/components/executer/excreate.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/executer/exdebug.c b/sys/contrib/dev/acpica/components/executer/exdebug.c
index 6a927eb26393..25b05477e06d 100644
--- a/sys/contrib/dev/acpica/components/executer/exdebug.c
+++ b/sys/contrib/dev/acpica/components/executer/exdebug.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/executer/exdump.c b/sys/contrib/dev/acpica/components/executer/exdump.c
index 581d183d919f..3a7e20e6d6ba 100644
--- a/sys/contrib/dev/acpica/components/executer/exdump.c
+++ b/sys/contrib/dev/acpica/components/executer/exdump.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/executer/exfield.c b/sys/contrib/dev/acpica/components/executer/exfield.c
index 6c27e7dfcb36..88dc6546fbd4 100644
--- a/sys/contrib/dev/acpica/components/executer/exfield.c
+++ b/sys/contrib/dev/acpica/components/executer/exfield.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/executer/exfldio.c b/sys/contrib/dev/acpica/components/executer/exfldio.c
index b3d1d73c0960..d164b1186edb 100644
--- a/sys/contrib/dev/acpica/components/executer/exfldio.c
+++ b/sys/contrib/dev/acpica/components/executer/exfldio.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/executer/exmisc.c b/sys/contrib/dev/acpica/components/executer/exmisc.c
index 9b9b6b3005c2..d1925921405b 100644
--- a/sys/contrib/dev/acpica/components/executer/exmisc.c
+++ b/sys/contrib/dev/acpica/components/executer/exmisc.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/executer/exmutex.c b/sys/contrib/dev/acpica/components/executer/exmutex.c
index fe1220d6abfb..cda70bcf7ccd 100644
--- a/sys/contrib/dev/acpica/components/executer/exmutex.c
+++ b/sys/contrib/dev/acpica/components/executer/exmutex.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/executer/exnames.c b/sys/contrib/dev/acpica/components/executer/exnames.c
index 105103f81f11..1d287c7e4956 100644
--- a/sys/contrib/dev/acpica/components/executer/exnames.c
+++ b/sys/contrib/dev/acpica/components/executer/exnames.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/executer/exoparg1.c b/sys/contrib/dev/acpica/components/executer/exoparg1.c
index 13af957693b4..b15335c0cc3e 100644
--- a/sys/contrib/dev/acpica/components/executer/exoparg1.c
+++ b/sys/contrib/dev/acpica/components/executer/exoparg1.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/executer/exoparg2.c b/sys/contrib/dev/acpica/components/executer/exoparg2.c
index 4bc3cf79e1eb..7dfcff0ece0e 100644
--- a/sys/contrib/dev/acpica/components/executer/exoparg2.c
+++ b/sys/contrib/dev/acpica/components/executer/exoparg2.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/executer/exoparg3.c b/sys/contrib/dev/acpica/components/executer/exoparg3.c
index 30de8487e676..e29b322ec9c2 100644
--- a/sys/contrib/dev/acpica/components/executer/exoparg3.c
+++ b/sys/contrib/dev/acpica/components/executer/exoparg3.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -225,11 +225,18 @@ AcpiExOpcode_3A_0T_0R (
AcpiOsSignal (ACPI_SIGNAL_FATAL, &Fatal);
+#ifndef ACPI_CONTINUE_ON_FATAL
/*
* Might return while OS is shutting down, so abort the AML execution
* by returning an error.
*/
return_ACPI_STATUS (AE_ERROR);
+#else
+ /*
+ * The alstests require that the Fatal() opcode does not return an error.
+ */
+ return_ACPI_STATUS (AE_OK);
+#endif
case AML_EXTERNAL_OP:
/*
@@ -313,7 +320,8 @@ AcpiExOpcode_3A_1T_1R (
/* Truncate request if larger than the actual String/Buffer */
- else if ((Index + Length) > Operand[0]->String.Length)
+ else if ((Index + Length) > Operand[0]->String.Length ||
+ (Index + Length) < Index) /* Check for overflow */
{
Length =
(ACPI_SIZE) Operand[0]->String.Length - (ACPI_SIZE) Index;
diff --git a/sys/contrib/dev/acpica/components/executer/exoparg6.c b/sys/contrib/dev/acpica/components/executer/exoparg6.c
index a9092ba2e4e2..9fe874576bec 100644
--- a/sys/contrib/dev/acpica/components/executer/exoparg6.c
+++ b/sys/contrib/dev/acpica/components/executer/exoparg6.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/executer/exprep.c b/sys/contrib/dev/acpica/components/executer/exprep.c
index dc04b77b7ea5..2f70b14d5f30 100644
--- a/sys/contrib/dev/acpica/components/executer/exprep.c
+++ b/sys/contrib/dev/acpica/components/executer/exprep.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/executer/exregion.c b/sys/contrib/dev/acpica/components/executer/exregion.c
index 4e9f535ef9ac..7d4e182f4fee 100644
--- a/sys/contrib/dev/acpica/components/executer/exregion.c
+++ b/sys/contrib/dev/acpica/components/executer/exregion.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/executer/exresnte.c b/sys/contrib/dev/acpica/components/executer/exresnte.c
index 0c66f0b4d4f8..3fad5e38beec 100644
--- a/sys/contrib/dev/acpica/components/executer/exresnte.c
+++ b/sys/contrib/dev/acpica/components/executer/exresnte.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/executer/exresolv.c b/sys/contrib/dev/acpica/components/executer/exresolv.c
index 81d934418983..62c26854511a 100644
--- a/sys/contrib/dev/acpica/components/executer/exresolv.c
+++ b/sys/contrib/dev/acpica/components/executer/exresolv.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/executer/exresop.c b/sys/contrib/dev/acpica/components/executer/exresop.c
index 0a89bc78d3e3..ad82bfad9d03 100644
--- a/sys/contrib/dev/acpica/components/executer/exresop.c
+++ b/sys/contrib/dev/acpica/components/executer/exresop.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/executer/exserial.c b/sys/contrib/dev/acpica/components/executer/exserial.c
index 6d17c29569e0..5b14147b75a2 100644
--- a/sys/contrib/dev/acpica/components/executer/exserial.c
+++ b/sys/contrib/dev/acpica/components/executer/exserial.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/executer/exstore.c b/sys/contrib/dev/acpica/components/executer/exstore.c
index ebe767abd637..b7776ae192af 100644
--- a/sys/contrib/dev/acpica/components/executer/exstore.c
+++ b/sys/contrib/dev/acpica/components/executer/exstore.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/executer/exstoren.c b/sys/contrib/dev/acpica/components/executer/exstoren.c
index ed9fa9a7f13b..07747f5e9f8a 100644
--- a/sys/contrib/dev/acpica/components/executer/exstoren.c
+++ b/sys/contrib/dev/acpica/components/executer/exstoren.c
@@ -9,7 +9,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/executer/exstorob.c b/sys/contrib/dev/acpica/components/executer/exstorob.c
index e9ddabd6c25a..5938a9a10036 100644
--- a/sys/contrib/dev/acpica/components/executer/exstorob.c
+++ b/sys/contrib/dev/acpica/components/executer/exstorob.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/executer/exsystem.c b/sys/contrib/dev/acpica/components/executer/exsystem.c
index f91d8d04b3ba..9a752d6e0366 100644
--- a/sys/contrib/dev/acpica/components/executer/exsystem.c
+++ b/sys/contrib/dev/acpica/components/executer/exsystem.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/executer/extrace.c b/sys/contrib/dev/acpica/components/executer/extrace.c
index b48a5fcb289b..49cf4d755bdd 100644
--- a/sys/contrib/dev/acpica/components/executer/extrace.c
+++ b/sys/contrib/dev/acpica/components/executer/extrace.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/executer/exutils.c b/sys/contrib/dev/acpica/components/executer/exutils.c
index 995edbc5990e..3f42b2466188 100644
--- a/sys/contrib/dev/acpica/components/executer/exutils.c
+++ b/sys/contrib/dev/acpica/components/executer/exutils.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/hardware/hwacpi.c b/sys/contrib/dev/acpica/components/hardware/hwacpi.c
index 74cfecfcc2a2..859659706ad2 100644
--- a/sys/contrib/dev/acpica/components/hardware/hwacpi.c
+++ b/sys/contrib/dev/acpica/components/hardware/hwacpi.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/hardware/hwesleep.c b/sys/contrib/dev/acpica/components/hardware/hwesleep.c
index 329d8a20b4b7..9c525ca72bdd 100644
--- a/sys/contrib/dev/acpica/components/hardware/hwesleep.c
+++ b/sys/contrib/dev/acpica/components/hardware/hwesleep.c
@@ -9,7 +9,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/hardware/hwgpe.c b/sys/contrib/dev/acpica/components/hardware/hwgpe.c
index 681ca9a1b9de..f4dbbc3faf25 100644
--- a/sys/contrib/dev/acpica/components/hardware/hwgpe.c
+++ b/sys/contrib/dev/acpica/components/hardware/hwgpe.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/hardware/hwpci.c b/sys/contrib/dev/acpica/components/hardware/hwpci.c
index a9fc5cba2fff..d0403dfb3ab3 100644
--- a/sys/contrib/dev/acpica/components/hardware/hwpci.c
+++ b/sys/contrib/dev/acpica/components/hardware/hwpci.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/hardware/hwregs.c b/sys/contrib/dev/acpica/components/hardware/hwregs.c
index d0f47b874ead..33ff9177f87f 100644
--- a/sys/contrib/dev/acpica/components/hardware/hwregs.c
+++ b/sys/contrib/dev/acpica/components/hardware/hwregs.c
@@ -9,7 +9,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/hardware/hwsleep.c b/sys/contrib/dev/acpica/components/hardware/hwsleep.c
index 210f4ea62dee..9503617ccc3f 100644
--- a/sys/contrib/dev/acpica/components/hardware/hwsleep.c
+++ b/sys/contrib/dev/acpica/components/hardware/hwsleep.c
@@ -9,7 +9,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/hardware/hwtimer.c b/sys/contrib/dev/acpica/components/hardware/hwtimer.c
index 9a9602e04232..95361aa3c1a0 100644
--- a/sys/contrib/dev/acpica/components/hardware/hwtimer.c
+++ b/sys/contrib/dev/acpica/components/hardware/hwtimer.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/hardware/hwvalid.c b/sys/contrib/dev/acpica/components/hardware/hwvalid.c
index 5c4df25d2c38..616b07101ba8 100644
--- a/sys/contrib/dev/acpica/components/hardware/hwvalid.c
+++ b/sys/contrib/dev/acpica/components/hardware/hwvalid.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/hardware/hwxface.c b/sys/contrib/dev/acpica/components/hardware/hwxface.c
index 5f645617cbce..4e5bf8c3f817 100644
--- a/sys/contrib/dev/acpica/components/hardware/hwxface.c
+++ b/sys/contrib/dev/acpica/components/hardware/hwxface.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/hardware/hwxfsleep.c b/sys/contrib/dev/acpica/components/hardware/hwxfsleep.c
index 1d79e908cf08..fd0563b4104f 100644
--- a/sys/contrib/dev/acpica/components/hardware/hwxfsleep.c
+++ b/sys/contrib/dev/acpica/components/hardware/hwxfsleep.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/namespace/nsaccess.c b/sys/contrib/dev/acpica/components/namespace/nsaccess.c
index 35d30ded0a60..2ef88ff7b5b6 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsaccess.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsaccess.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/namespace/nsalloc.c b/sys/contrib/dev/acpica/components/namespace/nsalloc.c
index 69d1d7fa053a..648c6ff8c13e 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsalloc.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsalloc.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/namespace/nsarguments.c b/sys/contrib/dev/acpica/components/namespace/nsarguments.c
index 8916484053b9..73ce74ab921d 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsarguments.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsarguments.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/namespace/nsconvert.c b/sys/contrib/dev/acpica/components/namespace/nsconvert.c
index ad4890b591a3..104324735436 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsconvert.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsconvert.c
@@ -9,7 +9,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/namespace/nsdump.c b/sys/contrib/dev/acpica/components/namespace/nsdump.c
index bf4aa1455075..300672e261ef 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsdump.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsdump.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/namespace/nsdumpdv.c b/sys/contrib/dev/acpica/components/namespace/nsdumpdv.c
index dc370a6e3018..172935d986e5 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsdumpdv.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsdumpdv.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/namespace/nseval.c b/sys/contrib/dev/acpica/components/namespace/nseval.c
index 765b270ad2a1..a977b65672be 100644
--- a/sys/contrib/dev/acpica/components/namespace/nseval.c
+++ b/sys/contrib/dev/acpica/components/namespace/nseval.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/namespace/nsinit.c b/sys/contrib/dev/acpica/components/namespace/nsinit.c
index ed37aee82502..da4775f1563e 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsinit.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsinit.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/namespace/nsload.c b/sys/contrib/dev/acpica/components/namespace/nsload.c
index bbd36a8a29a3..c81ecde79239 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsload.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsload.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/namespace/nsnames.c b/sys/contrib/dev/acpica/components/namespace/nsnames.c
index a5aa1139792d..c1fc31b4bdad 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsnames.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsnames.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -400,6 +400,13 @@ AcpiNsBuildNormalizedPath (
goto BuildTrailingNull;
}
+ /* Validate the Node to avoid use-after-free vulnerabilities */
+
+ if (ACPI_GET_DESCRIPTOR_TYPE (Node) != ACPI_DESC_TYPE_NAMED)
+ {
+ goto BuildTrailingNull;
+ }
+
NextNode = Node;
while (NextNode && NextNode != AcpiGbl_RootNode)
{
diff --git a/sys/contrib/dev/acpica/components/namespace/nsobject.c b/sys/contrib/dev/acpica/components/namespace/nsobject.c
index fd6f0a524699..246d93ce74f6 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsobject.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsobject.c
@@ -9,7 +9,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -336,6 +336,13 @@ AcpiNsDetachObject (
ObjDesc = Node->Object;
+ /* Alias nodes point directly to other namespace nodes; skip teardown */
+ if (Node->Flags & ANOBJ_IS_ALIAS)
+ {
+ Node->Object = NULL;
+ return_VOID;
+ }
+
if (!ObjDesc ||
(ObjDesc->Common.Type == ACPI_TYPE_LOCAL_DATA))
{
diff --git a/sys/contrib/dev/acpica/components/namespace/nsparse.c b/sys/contrib/dev/acpica/components/namespace/nsparse.c
index c5d35bac831c..ee9e9a6ce035 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsparse.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsparse.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/namespace/nspredef.c b/sys/contrib/dev/acpica/components/namespace/nspredef.c
index 5bb5d5bf67ca..b63a1e2ada26 100644
--- a/sys/contrib/dev/acpica/components/namespace/nspredef.c
+++ b/sys/contrib/dev/acpica/components/namespace/nspredef.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/namespace/nsprepkg.c b/sys/contrib/dev/acpica/components/namespace/nsprepkg.c
index 6fced55328bf..2deadcf39d75 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsprepkg.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsprepkg.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -779,6 +779,13 @@ AcpiNsCustomPackage (
/* Get version number, must be Integer */
+ if (!(*Elements))
+ {
+ ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
+ "Return Package has a NULL version element"));
+ return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ }
+
if ((*Elements)->Common.Type != ACPI_TYPE_INTEGER)
{
ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
diff --git a/sys/contrib/dev/acpica/components/namespace/nsrepair.c b/sys/contrib/dev/acpica/components/namespace/nsrepair.c
index 8d0e86932e1d..edecc8ddfd6c 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsrepair.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsrepair.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/namespace/nsrepair2.c b/sys/contrib/dev/acpica/components/namespace/nsrepair2.c
index 0dddebda980b..c70e3b9027a7 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsrepair2.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsrepair2.c
@@ -9,7 +9,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/namespace/nssearch.c b/sys/contrib/dev/acpica/components/namespace/nssearch.c
index d956358e8e35..8e6fa7cae3f9 100644
--- a/sys/contrib/dev/acpica/components/namespace/nssearch.c
+++ b/sys/contrib/dev/acpica/components/namespace/nssearch.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/namespace/nsutils.c b/sys/contrib/dev/acpica/components/namespace/nsutils.c
index bf400ed2370d..20031654469d 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsutils.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsutils.c
@@ -9,7 +9,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/namespace/nswalk.c b/sys/contrib/dev/acpica/components/namespace/nswalk.c
index 14a608bc28fe..0ef306cc5629 100644
--- a/sys/contrib/dev/acpica/components/namespace/nswalk.c
+++ b/sys/contrib/dev/acpica/components/namespace/nswalk.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/namespace/nsxfeval.c b/sys/contrib/dev/acpica/components/namespace/nsxfeval.c
index f6a1ead7ddd5..b996bf834469 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsxfeval.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsxfeval.c
@@ -9,7 +9,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/namespace/nsxfname.c b/sys/contrib/dev/acpica/components/namespace/nsxfname.c
index 94800cb531c6..9b18825c0473 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsxfname.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsxfname.c
@@ -9,7 +9,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/namespace/nsxfobj.c b/sys/contrib/dev/acpica/components/namespace/nsxfobj.c
index ea0654285a90..42dd10828614 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsxfobj.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsxfobj.c
@@ -9,7 +9,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/parser/psargs.c b/sys/contrib/dev/acpica/components/parser/psargs.c
index d9110c09fcb5..fecb11677c31 100644
--- a/sys/contrib/dev/acpica/components/parser/psargs.c
+++ b/sys/contrib/dev/acpica/components/parser/psargs.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -197,6 +197,7 @@ AcpiPsGetNextPackageLength (
UINT32 PackageLength = 0;
UINT32 ByteCount;
UINT8 ByteZeroMask = 0x3F; /* Default [0:5] */
+ UINT32 Remaining;
ACPI_FUNCTION_TRACE (PsGetNextPackageLength);
@@ -206,7 +207,24 @@ AcpiPsGetNextPackageLength (
* Byte 0 bits [6:7] contain the number of additional bytes
* used to encode the package length, either 0,1,2, or 3
*/
+
+ /* Check if we have at least one byte to read */
+ Remaining = (UINT32) ACPI_PTR_DIFF (ParserState->AmlEnd, Aml);
+ if (Remaining == 0)
+ {
+ return_UINT32 (0);
+ }
+
ByteCount = (Aml[0] >> 6);
+
+ /* Validate ByteCount and ensure we have enough bytes to read */
+ if (ByteCount >= Remaining)
+ {
+ /* Clamp to available bytes and advance to end */
+ ParserState->Aml = ParserState->AmlEnd;
+ return_UINT32 (0);
+ }
+
ParserState->Aml += ((ACPI_SIZE) ByteCount + 1);
/* Get bytes 3, 2, 1 as needed */
@@ -545,6 +563,8 @@ AcpiPsGetNextSimpleArg (
UINT32 Length;
UINT16 Opcode;
UINT8 *Aml = ParserState->Aml;
+ UINT32 Remaining = (UINT32) ACPI_PTR_DIFF (ParserState->AmlEnd, Aml);
+ UINT64 PartialValue;
ACPI_FUNCTION_TRACE_U32 (PsGetNextSimpleArg, ArgType);
@@ -557,8 +577,16 @@ AcpiPsGetNextSimpleArg (
/* Get 1 byte from the AML stream */
Opcode = AML_BYTE_OP;
- Arg->Common.Value.Integer = (UINT64) *Aml;
- Length = 1;
+ if (Remaining >= 1)
+ {
+ Arg->Common.Value.Integer = (UINT64) *Aml;
+ Length = 1;
+ }
+ else
+ {
+ Arg->Common.Value.Integer = 0;
+ Length = 0;
+ }
break;
case ARGP_WORDDATA:
@@ -566,8 +594,23 @@ AcpiPsGetNextSimpleArg (
/* Get 2 bytes from the AML stream */
Opcode = AML_WORD_OP;
- ACPI_MOVE_16_TO_64 (&Arg->Common.Value.Integer, Aml);
- Length = 2;
+ if (Remaining >= 2)
+ {
+ ACPI_MOVE_16_TO_64 (&Arg->Common.Value.Integer, Aml);
+ Length = 2;
+ }
+ else
+ {
+ Arg->Common.Value.Integer = 0;
+ Length = 0;
+ if (Remaining > 0)
+ {
+ PartialValue = 0;
+ memcpy (&PartialValue, Aml, Remaining);
+ Arg->Common.Value.Integer = PartialValue;
+ Length = Remaining;
+ }
+ }
break;
case ARGP_DWORDDATA:
@@ -575,8 +618,23 @@ AcpiPsGetNextSimpleArg (
/* Get 4 bytes from the AML stream */
Opcode = AML_DWORD_OP;
- ACPI_MOVE_32_TO_64 (&Arg->Common.Value.Integer, Aml);
- Length = 4;
+ if (Remaining >= 4)
+ {
+ ACPI_MOVE_32_TO_64 (&Arg->Common.Value.Integer, Aml);
+ Length = 4;
+ }
+ else
+ {
+ Arg->Common.Value.Integer = 0;
+ Length = 0;
+ if (Remaining > 0)
+ {
+ PartialValue = 0;
+ memcpy (&PartialValue, Aml, Remaining);
+ Arg->Common.Value.Integer = PartialValue;
+ Length = Remaining;
+ }
+ }
break;
case ARGP_QWORDDATA:
@@ -584,8 +642,23 @@ AcpiPsGetNextSimpleArg (
/* Get 8 bytes from the AML stream */
Opcode = AML_QWORD_OP;
- ACPI_MOVE_64_TO_64 (&Arg->Common.Value.Integer, Aml);
- Length = 8;
+ if (Remaining >= 8)
+ {
+ ACPI_MOVE_64_TO_64 (&Arg->Common.Value.Integer, Aml);
+ Length = 8;
+ }
+ else
+ {
+ Arg->Common.Value.Integer = 0;
+ Length = 0;
+ if (Remaining > 0)
+ {
+ PartialValue = 0;
+ memcpy (&PartialValue, Aml, Remaining);
+ Arg->Common.Value.Integer = PartialValue;
+ Length = Remaining;
+ }
+ }
break;
case ARGP_CHARLIST:
@@ -598,11 +671,32 @@ AcpiPsGetNextSimpleArg (
/* Find the null terminator */
Length = 0;
- while (Aml[Length])
+ while ((Length < Remaining) && Aml[Length])
+ {
+ Length++;
+ }
+ if (Length < Remaining)
{
+ /* Account for the terminating null */
Length++;
}
- Length++;
+ else
+ {
+ /*
+ * No terminator found - add null at buffer boundary
+ * and report a warning
+ */
+ ACPI_WARNING ((AE_INFO,
+ "Invalid AML string: no null terminator, truncating at offset %u",
+ (UINT32) (Aml - ParserState->Aml)));
+
+ /* Add null terminator at the boundary */
+ if (Remaining > 0)
+ {
+ Aml[Remaining - 1] = 0;
+ Length = Remaining;
+ }
+ }
break;
case ARGP_NAME:
@@ -659,6 +753,11 @@ AcpiPsGetNextField (
ASL_CV_CAPTURE_COMMENTS_ONLY (ParserState);
Aml = ParserState->Aml;
+ if (Aml >= ParserState->AmlEnd)
+ {
+ return_PTR (NULL);
+ }
+
/* Determine field type */
switch (ACPI_GET8 (ParserState->Aml))
@@ -710,6 +809,11 @@ AcpiPsGetNextField (
/* Get the 4-character name */
+ if ((ParserState->Aml + ACPI_NAMESEG_SIZE) > ParserState->AmlEnd)
+ {
+ AcpiPsFreeOp (Field);
+ return_PTR (NULL);
+ }
ACPI_MOVE_32_TO_32 (&Name, ParserState->Aml);
AcpiPsSetName (Field, Name);
ParserState->Aml += ACPI_NAMESEG_SIZE;
@@ -756,6 +860,11 @@ AcpiPsGetNextField (
/* Get the two bytes (Type/Attribute) */
+ if ((ParserState->Aml + 2) > ParserState->AmlEnd)
+ {
+ AcpiPsFreeOp (Field);
+ return_PTR (NULL);
+ }
AccessType = ACPI_GET8 (ParserState->Aml);
ParserState->Aml++;
AccessAttribute = ACPI_GET8 (ParserState->Aml);
@@ -768,6 +877,11 @@ AcpiPsGetNextField (
if (Opcode == AML_INT_EXTACCESSFIELD_OP)
{
+ if (ParserState->Aml >= ParserState->AmlEnd)
+ {
+ AcpiPsFreeOp (Field);
+ return_PTR (NULL);
+ }
AccessLength = ACPI_GET8 (ParserState->Aml);
ParserState->Aml++;
diff --git a/sys/contrib/dev/acpica/components/parser/psloop.c b/sys/contrib/dev/acpica/components/parser/psloop.c
index f4cac83e6069..b7e4bac02e09 100644
--- a/sys/contrib/dev/acpica/components/parser/psloop.c
+++ b/sys/contrib/dev/acpica/components/parser/psloop.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -566,7 +566,8 @@ AcpiPsParseLoop (
WalkState->Aml = ParserState->Aml;
ACPI_ERROR ((AE_INFO, "Skipping While/If block"));
- if (*WalkState->Aml == AML_ELSE_OP)
+ if ((WalkState->Aml < ParserState->AmlEnd) &&
+ (*WalkState->Aml == AML_ELSE_OP))
{
ACPI_ERROR ((AE_INFO, "Skipping Else block"));
WalkState->ParserState.Aml = WalkState->Aml + 1;
diff --git a/sys/contrib/dev/acpica/components/parser/psobject.c b/sys/contrib/dev/acpica/components/parser/psobject.c
index 5457d9d0be7d..5039d81c05ef 100644
--- a/sys/contrib/dev/acpica/components/parser/psobject.c
+++ b/sys/contrib/dev/acpica/components/parser/psobject.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/parser/psopcode.c b/sys/contrib/dev/acpica/components/parser/psopcode.c
index a317fab3005e..a8bba0cefc0d 100644
--- a/sys/contrib/dev/acpica/components/parser/psopcode.c
+++ b/sys/contrib/dev/acpica/components/parser/psopcode.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/parser/psopinfo.c b/sys/contrib/dev/acpica/components/parser/psopinfo.c
index 1db32f4e8246..8ebcf05f1a66 100644
--- a/sys/contrib/dev/acpica/components/parser/psopinfo.c
+++ b/sys/contrib/dev/acpica/components/parser/psopinfo.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/parser/psparse.c b/sys/contrib/dev/acpica/components/parser/psparse.c
index f294033a0039..1cb4dd905036 100644
--- a/sys/contrib/dev/acpica/components/parser/psparse.c
+++ b/sys/contrib/dev/acpica/components/parser/psparse.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/parser/psscope.c b/sys/contrib/dev/acpica/components/parser/psscope.c
index 4f9f496f5018..cb1d2abf815a 100644
--- a/sys/contrib/dev/acpica/components/parser/psscope.c
+++ b/sys/contrib/dev/acpica/components/parser/psscope.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/parser/pstree.c b/sys/contrib/dev/acpica/components/parser/pstree.c
index b561ba4b0721..657d59064dea 100644
--- a/sys/contrib/dev/acpica/components/parser/pstree.c
+++ b/sys/contrib/dev/acpica/components/parser/pstree.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/parser/psutils.c b/sys/contrib/dev/acpica/components/parser/psutils.c
index 3c647940e287..8554264f8c30 100644
--- a/sys/contrib/dev/acpica/components/parser/psutils.c
+++ b/sys/contrib/dev/acpica/components/parser/psutils.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/parser/pswalk.c b/sys/contrib/dev/acpica/components/parser/pswalk.c
index a0941d44cc03..174e6aefec19 100644
--- a/sys/contrib/dev/acpica/components/parser/pswalk.c
+++ b/sys/contrib/dev/acpica/components/parser/pswalk.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -198,7 +198,7 @@ AcpiPsDeleteParseTree (
{
/* This debug option will print the entire parse tree */
- AcpiOsPrintf (" %*.s%s %p", (Level * 4), " ",
+ AcpiOsPrintf (" %*s%s %p", (Level * 4), "",
AcpiPsGetOpcodeName (Op->Common.AmlOpcode), Op);
if (Op->Named.AmlOpcode == AML_INT_NAMEPATH_OP)
diff --git a/sys/contrib/dev/acpica/components/parser/psxface.c b/sys/contrib/dev/acpica/components/parser/psxface.c
index 08c1c2bb4f0d..2fad9ccd030e 100644
--- a/sys/contrib/dev/acpica/components/parser/psxface.c
+++ b/sys/contrib/dev/acpica/components/parser/psxface.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/resources/rsaddr.c b/sys/contrib/dev/acpica/components/resources/rsaddr.c
index 9074c6dbaa35..bb07db852451 100644
--- a/sys/contrib/dev/acpica/components/resources/rsaddr.c
+++ b/sys/contrib/dev/acpica/components/resources/rsaddr.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/resources/rscalc.c b/sys/contrib/dev/acpica/components/resources/rscalc.c
index fc7575c2ddfb..daffc696803d 100644
--- a/sys/contrib/dev/acpica/components/resources/rscalc.c
+++ b/sys/contrib/dev/acpica/components/resources/rscalc.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/resources/rscreate.c b/sys/contrib/dev/acpica/components/resources/rscreate.c
index b930ced8396f..a625b65194dc 100644
--- a/sys/contrib/dev/acpica/components/resources/rscreate.c
+++ b/sys/contrib/dev/acpica/components/resources/rscreate.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/resources/rsdump.c b/sys/contrib/dev/acpica/components/resources/rsdump.c
index 2f3e996af9af..d485b047d24e 100644
--- a/sys/contrib/dev/acpica/components/resources/rsdump.c
+++ b/sys/contrib/dev/acpica/components/resources/rsdump.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/resources/rsdumpinfo.c b/sys/contrib/dev/acpica/components/resources/rsdumpinfo.c
index 293eeb596928..4238772408fb 100644
--- a/sys/contrib/dev/acpica/components/resources/rsdumpinfo.c
+++ b/sys/contrib/dev/acpica/components/resources/rsdumpinfo.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/resources/rsinfo.c b/sys/contrib/dev/acpica/components/resources/rsinfo.c
index 7a1bb07abb94..222ef95c600b 100644
--- a/sys/contrib/dev/acpica/components/resources/rsinfo.c
+++ b/sys/contrib/dev/acpica/components/resources/rsinfo.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/resources/rsio.c b/sys/contrib/dev/acpica/components/resources/rsio.c
index 46d9b2f8aa4b..b51cb2ed18dd 100644
--- a/sys/contrib/dev/acpica/components/resources/rsio.c
+++ b/sys/contrib/dev/acpica/components/resources/rsio.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/resources/rsirq.c b/sys/contrib/dev/acpica/components/resources/rsirq.c
index 80482eb097d6..a1c32a13ffbd 100644
--- a/sys/contrib/dev/acpica/components/resources/rsirq.c
+++ b/sys/contrib/dev/acpica/components/resources/rsirq.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/resources/rslist.c b/sys/contrib/dev/acpica/components/resources/rslist.c
index 2de70ad4fc58..0f6c6ad2ac4a 100644
--- a/sys/contrib/dev/acpica/components/resources/rslist.c
+++ b/sys/contrib/dev/acpica/components/resources/rslist.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/resources/rsmemory.c b/sys/contrib/dev/acpica/components/resources/rsmemory.c
index 0430379a0f05..7a274e6695ba 100644
--- a/sys/contrib/dev/acpica/components/resources/rsmemory.c
+++ b/sys/contrib/dev/acpica/components/resources/rsmemory.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/resources/rsmisc.c b/sys/contrib/dev/acpica/components/resources/rsmisc.c
index 725a130a2cec..72165acfffa9 100644
--- a/sys/contrib/dev/acpica/components/resources/rsmisc.c
+++ b/sys/contrib/dev/acpica/components/resources/rsmisc.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/resources/rsserial.c b/sys/contrib/dev/acpica/components/resources/rsserial.c
index ab09939850c0..55fb82d8ffff 100644
--- a/sys/contrib/dev/acpica/components/resources/rsserial.c
+++ b/sys/contrib/dev/acpica/components/resources/rsserial.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -447,7 +447,7 @@ ACPI_RSCONVERT_INFO AcpiRsConvertCsi2SerialBus[14] =
*
******************************************************************************/
-ACPI_RSCONVERT_INFO AcpiRsConvertI2cSerialBus[17] =
+ACPI_RSCONVERT_INFO AcpiRsConvertI2cSerialBus[18] =
{
{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_SERIAL_BUS,
ACPI_RS_SIZE (ACPI_RESOURCE_I2C_SERIALBUS),
@@ -515,6 +515,11 @@ ACPI_RSCONVERT_INFO AcpiRsConvertI2cSerialBus[17] =
AML_OFFSET (I2cSerialBus.TypeSpecificFlags),
0},
+ /* Read LVR from Type Specific Flags, bits[15:8] */
+ {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.I2cSerialBus.Lvr),
+ AML_OFFSET (I2cSerialBus.TypeSpecificFlags) + 1,
+ 1},
+
{ACPI_RSC_MOVE32, ACPI_RS_OFFSET (Data.I2cSerialBus.ConnectionSpeed),
AML_OFFSET (I2cSerialBus.ConnectionSpeed),
1},
diff --git a/sys/contrib/dev/acpica/components/resources/rsutils.c b/sys/contrib/dev/acpica/components/resources/rsutils.c
index cc89fcfbb356..e9e797e43e1e 100644
--- a/sys/contrib/dev/acpica/components/resources/rsutils.c
+++ b/sys/contrib/dev/acpica/components/resources/rsutils.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/resources/rsxface.c b/sys/contrib/dev/acpica/components/resources/rsxface.c
index 89cc58864ead..ada8a44448fc 100644
--- a/sys/contrib/dev/acpica/components/resources/rsxface.c
+++ b/sys/contrib/dev/acpica/components/resources/rsxface.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/tables/tbdata.c b/sys/contrib/dev/acpica/components/tables/tbdata.c
index 46c7724bdda4..b36e971fcceb 100644
--- a/sys/contrib/dev/acpica/components/tables/tbdata.c
+++ b/sys/contrib/dev/acpica/components/tables/tbdata.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/tables/tbfadt.c b/sys/contrib/dev/acpica/components/tables/tbfadt.c
index 70490b5d0e70..8fea0572eb74 100644
--- a/sys/contrib/dev/acpica/components/tables/tbfadt.c
+++ b/sys/contrib/dev/acpica/components/tables/tbfadt.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -736,8 +736,11 @@ AcpiTbConvertFadt (
* Note: If the legacy length field is > 0xFF bits, ignore
* this check. (GPE registers can be larger than the
* 64-bit GAS structure can accommodate, 0xFF bits).
+ * Also skip if BitWidth is 0, indicating the 64-bit field
+ * was not populated - legacy length will be used instead.
*/
if ((ACPI_MUL_8 (Length) <= ACPI_UINT8_MAX) &&
+ (Address64->BitWidth != 0) &&
(Address64->BitWidth != ACPI_MUL_8 (Length)))
{
ACPI_BIOS_WARNING ((AE_INFO,
diff --git a/sys/contrib/dev/acpica/components/tables/tbfind.c b/sys/contrib/dev/acpica/components/tables/tbfind.c
index e497cca9b553..070debef1fac 100644
--- a/sys/contrib/dev/acpica/components/tables/tbfind.c
+++ b/sys/contrib/dev/acpica/components/tables/tbfind.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/tables/tbinstal.c b/sys/contrib/dev/acpica/components/tables/tbinstal.c
index 309ec5b68472..aa508042910e 100644
--- a/sys/contrib/dev/acpica/components/tables/tbinstal.c
+++ b/sys/contrib/dev/acpica/components/tables/tbinstal.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/tables/tbprint.c b/sys/contrib/dev/acpica/components/tables/tbprint.c
index cc4badd84801..01dee2953fc8 100644
--- a/sys/contrib/dev/acpica/components/tables/tbprint.c
+++ b/sys/contrib/dev/acpica/components/tables/tbprint.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/tables/tbutils.c b/sys/contrib/dev/acpica/components/tables/tbutils.c
index 61d8ac597afa..db18a24413fe 100644
--- a/sys/contrib/dev/acpica/components/tables/tbutils.c
+++ b/sys/contrib/dev/acpica/components/tables/tbutils.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/tables/tbxface.c b/sys/contrib/dev/acpica/components/tables/tbxface.c
index 0b16c0a9ebec..7e732809b6a1 100644
--- a/sys/contrib/dev/acpica/components/tables/tbxface.c
+++ b/sys/contrib/dev/acpica/components/tables/tbxface.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/tables/tbxfload.c b/sys/contrib/dev/acpica/components/tables/tbxfload.c
index af49869d626c..f3c8d0b900ae 100644
--- a/sys/contrib/dev/acpica/components/tables/tbxfload.c
+++ b/sys/contrib/dev/acpica/components/tables/tbxfload.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/tables/tbxfroot.c b/sys/contrib/dev/acpica/components/tables/tbxfroot.c
index 7c444bda9c8c..7e4b05abe60f 100644
--- a/sys/contrib/dev/acpica/components/tables/tbxfroot.c
+++ b/sys/contrib/dev/acpica/components/tables/tbxfroot.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/utilities/utaddress.c b/sys/contrib/dev/acpica/components/utilities/utaddress.c
index 7ea0ff3e91b7..d7296a08f6e5 100644
--- a/sys/contrib/dev/acpica/components/utilities/utaddress.c
+++ b/sys/contrib/dev/acpica/components/utilities/utaddress.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/utilities/utalloc.c b/sys/contrib/dev/acpica/components/utilities/utalloc.c
index 0dfdec633c2f..7b7d86a7268c 100644
--- a/sys/contrib/dev/acpica/components/utilities/utalloc.c
+++ b/sys/contrib/dev/acpica/components/utilities/utalloc.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/utilities/utascii.c b/sys/contrib/dev/acpica/components/utilities/utascii.c
index cf64bdee02df..925355121184 100644
--- a/sys/contrib/dev/acpica/components/utilities/utascii.c
+++ b/sys/contrib/dev/acpica/components/utilities/utascii.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/utilities/utbuffer.c b/sys/contrib/dev/acpica/components/utilities/utbuffer.c
index b22530412b2f..c72b3065e03e 100644
--- a/sys/contrib/dev/acpica/components/utilities/utbuffer.c
+++ b/sys/contrib/dev/acpica/components/utilities/utbuffer.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/utilities/utcache.c b/sys/contrib/dev/acpica/components/utilities/utcache.c
index 232154696307..271920a69134 100644
--- a/sys/contrib/dev/acpica/components/utilities/utcache.c
+++ b/sys/contrib/dev/acpica/components/utilities/utcache.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/utilities/utcksum.c b/sys/contrib/dev/acpica/components/utilities/utcksum.c
index 50f8f80570ef..c9d137a7ef3a 100644
--- a/sys/contrib/dev/acpica/components/utilities/utcksum.c
+++ b/sys/contrib/dev/acpica/components/utilities/utcksum.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/utilities/utcopy.c b/sys/contrib/dev/acpica/components/utilities/utcopy.c
index fd4d6922a1f2..3a3f4d317385 100644
--- a/sys/contrib/dev/acpica/components/utilities/utcopy.c
+++ b/sys/contrib/dev/acpica/components/utilities/utcopy.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -918,7 +918,16 @@ AcpiUtCopySimpleObject (
break;
}
- AcpiUtAddReference (SourceDesc->Reference.Object);
+ /*
+ * Local/Arg/Debug references do not have a valid Object pointer
+ * that can be referenced
+ */
+ if ((SourceDesc->Reference.Class != ACPI_REFCLASS_LOCAL) &&
+ (SourceDesc->Reference.Class != ACPI_REFCLASS_ARG) &&
+ (SourceDesc->Reference.Class != ACPI_REFCLASS_DEBUG))
+ {
+ AcpiUtAddReference (SourceDesc->Reference.Object);
+ }
break;
case ACPI_TYPE_REGION:
diff --git a/sys/contrib/dev/acpica/components/utilities/utdebug.c b/sys/contrib/dev/acpica/components/utilities/utdebug.c
index 90b8e246a1a9..1b6b56fca02d 100644
--- a/sys/contrib/dev/acpica/components/utilities/utdebug.c
+++ b/sys/contrib/dev/acpica/components/utilities/utdebug.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/utilities/utdecode.c b/sys/contrib/dev/acpica/components/utilities/utdecode.c
index 00a2de9e9a5d..85a948476d05 100644
--- a/sys/contrib/dev/acpica/components/utilities/utdecode.c
+++ b/sys/contrib/dev/acpica/components/utilities/utdecode.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/utilities/utdelete.c b/sys/contrib/dev/acpica/components/utilities/utdelete.c
index e88cc736990b..2668398ac4cc 100644
--- a/sys/contrib/dev/acpica/components/utilities/utdelete.c
+++ b/sys/contrib/dev/acpica/components/utilities/utdelete.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/utilities/uterror.c b/sys/contrib/dev/acpica/components/utilities/uterror.c
index 1537f69a2a2b..1eec656e0c56 100644
--- a/sys/contrib/dev/acpica/components/utilities/uterror.c
+++ b/sys/contrib/dev/acpica/components/utilities/uterror.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/utilities/uteval.c b/sys/contrib/dev/acpica/components/utilities/uteval.c
index 53f843062179..ab0109c88af9 100644
--- a/sys/contrib/dev/acpica/components/utilities/uteval.c
+++ b/sys/contrib/dev/acpica/components/utilities/uteval.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/utilities/utexcep.c b/sys/contrib/dev/acpica/components/utilities/utexcep.c
index b3e606ceef57..c1bd798f146e 100644
--- a/sys/contrib/dev/acpica/components/utilities/utexcep.c
+++ b/sys/contrib/dev/acpica/components/utilities/utexcep.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/utilities/utglobal.c b/sys/contrib/dev/acpica/components/utilities/utglobal.c
index 95d679a20746..ec24f1f1f9ac 100644
--- a/sys/contrib/dev/acpica/components/utilities/utglobal.c
+++ b/sys/contrib/dev/acpica/components/utilities/utglobal.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/utilities/uthex.c b/sys/contrib/dev/acpica/components/utilities/uthex.c
index 2806f1c48148..751f7af6501f 100644
--- a/sys/contrib/dev/acpica/components/utilities/uthex.c
+++ b/sys/contrib/dev/acpica/components/utilities/uthex.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/utilities/utids.c b/sys/contrib/dev/acpica/components/utilities/utids.c
index 3dfb908302c6..0fffb8377c83 100644
--- a/sys/contrib/dev/acpica/components/utilities/utids.c
+++ b/sys/contrib/dev/acpica/components/utilities/utids.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/utilities/utinit.c b/sys/contrib/dev/acpica/components/utilities/utinit.c
index b5a4b7e7d936..a32361a53e17 100644
--- a/sys/contrib/dev/acpica/components/utilities/utinit.c
+++ b/sys/contrib/dev/acpica/components/utilities/utinit.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/utilities/utlock.c b/sys/contrib/dev/acpica/components/utilities/utlock.c
index a06b27525cc3..4f4c3036bc4f 100644
--- a/sys/contrib/dev/acpica/components/utilities/utlock.c
+++ b/sys/contrib/dev/acpica/components/utilities/utlock.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/utilities/utmath.c b/sys/contrib/dev/acpica/components/utilities/utmath.c
index 48bbe8f3d8c8..c9c5bd3f2a31 100644
--- a/sys/contrib/dev/acpica/components/utilities/utmath.c
+++ b/sys/contrib/dev/acpica/components/utilities/utmath.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/utilities/utmisc.c b/sys/contrib/dev/acpica/components/utilities/utmisc.c
index 13dffc6674d3..4723349ac6f3 100644
--- a/sys/contrib/dev/acpica/components/utilities/utmisc.c
+++ b/sys/contrib/dev/acpica/components/utilities/utmisc.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/utilities/utmutex.c b/sys/contrib/dev/acpica/components/utilities/utmutex.c
index b0b26458818e..ba1d477b0bed 100644
--- a/sys/contrib/dev/acpica/components/utilities/utmutex.c
+++ b/sys/contrib/dev/acpica/components/utilities/utmutex.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/utilities/utnonansi.c b/sys/contrib/dev/acpica/components/utilities/utnonansi.c
index f8b3a29e3283..e6cacbad00e8 100644
--- a/sys/contrib/dev/acpica/components/utilities/utnonansi.c
+++ b/sys/contrib/dev/acpica/components/utilities/utnonansi.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/utilities/utobject.c b/sys/contrib/dev/acpica/components/utilities/utobject.c
index 6988afdcbaec..3e388dd1a968 100644
--- a/sys/contrib/dev/acpica/components/utilities/utobject.c
+++ b/sys/contrib/dev/acpica/components/utilities/utobject.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/utilities/utosi.c b/sys/contrib/dev/acpica/components/utilities/utosi.c
index 7118313f7b16..fc886276a3ab 100644
--- a/sys/contrib/dev/acpica/components/utilities/utosi.c
+++ b/sys/contrib/dev/acpica/components/utilities/utosi.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/utilities/utownerid.c b/sys/contrib/dev/acpica/components/utilities/utownerid.c
index 7e39b7851af4..40139f481c87 100644
--- a/sys/contrib/dev/acpica/components/utilities/utownerid.c
+++ b/sys/contrib/dev/acpica/components/utilities/utownerid.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/utilities/utpredef.c b/sys/contrib/dev/acpica/components/utilities/utpredef.c
index 23e6606d167c..3131e16f046f 100644
--- a/sys/contrib/dev/acpica/components/utilities/utpredef.c
+++ b/sys/contrib/dev/acpica/components/utilities/utpredef.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/utilities/utresdecode.c b/sys/contrib/dev/acpica/components/utilities/utresdecode.c
index d14259911a07..8ff5dd12cc5f 100644
--- a/sys/contrib/dev/acpica/components/utilities/utresdecode.c
+++ b/sys/contrib/dev/acpica/components/utilities/utresdecode.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/utilities/utresrc.c b/sys/contrib/dev/acpica/components/utilities/utresrc.c
index 109395435d45..5a1220c6ee70 100644
--- a/sys/contrib/dev/acpica/components/utilities/utresrc.c
+++ b/sys/contrib/dev/acpica/components/utilities/utresrc.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -322,6 +322,29 @@ AcpiUtWalkAmlResources (
while (Aml < EndAml)
{
+ /*
+ * Validate that the remaining buffer space can hold enough
+ * bytes to safely access fields during validation.
+ * For large resource descriptors (bit 7 set), we need enough
+ * bytes to access the Type field in SerialBus resources.
+ * Small resource descriptors only need sizeof(AML_RESOURCE_END_TAG).
+ */
+ if ((ACPI_SIZE) (EndAml - Aml) < sizeof (AML_RESOURCE_END_TAG))
+ {
+ return_ACPI_STATUS (AE_AML_BUFFER_LENGTH);
+ }
+
+ /*
+ * For large resource descriptors, ensure enough space for
+ * the header plus SerialBus Type field access.
+ */
+ if ((ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_LARGE) &&
+ ((ACPI_SIZE) (EndAml - Aml) <
+ ACPI_OFFSET (AML_RESOURCE_COMMON_SERIALBUS, Type) + 1))
+ {
+ return_ACPI_STATUS (AE_AML_BUFFER_LENGTH);
+ }
+
/* Validate the Resource Type and Resource Length */
Status = AcpiUtValidateResource (WalkState, Aml, &ResourceIndex);
@@ -338,6 +361,15 @@ AcpiUtWalkAmlResources (
Length = AcpiUtGetDescriptorLength (Aml);
+ /*
+ * Validate that the descriptor length doesn't exceed the
+ * remaining buffer size to prevent reading beyond the end.
+ */
+ if (Length > (ACPI_SIZE) (EndAml - Aml))
+ {
+ return_ACPI_STATUS (AE_AML_BUFFER_LENGTH);
+ }
+
/* Invoke the user function */
if (UserFunction)
diff --git a/sys/contrib/dev/acpica/components/utilities/utstate.c b/sys/contrib/dev/acpica/components/utilities/utstate.c
index 02fec7d15bf5..5789cd3309d1 100644
--- a/sys/contrib/dev/acpica/components/utilities/utstate.c
+++ b/sys/contrib/dev/acpica/components/utilities/utstate.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/utilities/utstring.c b/sys/contrib/dev/acpica/components/utilities/utstring.c
index 59e34e7c8a79..5ece4de3c50b 100644
--- a/sys/contrib/dev/acpica/components/utilities/utstring.c
+++ b/sys/contrib/dev/acpica/components/utilities/utstring.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/utilities/utstrsuppt.c b/sys/contrib/dev/acpica/components/utilities/utstrsuppt.c
index 1537d8a02949..4d54ab287e91 100644
--- a/sys/contrib/dev/acpica/components/utilities/utstrsuppt.c
+++ b/sys/contrib/dev/acpica/components/utilities/utstrsuppt.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/utilities/utstrtoul64.c b/sys/contrib/dev/acpica/components/utilities/utstrtoul64.c
index 2683c37c35db..75659ef3d9c5 100644
--- a/sys/contrib/dev/acpica/components/utilities/utstrtoul64.c
+++ b/sys/contrib/dev/acpica/components/utilities/utstrtoul64.c
@@ -9,7 +9,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/utilities/uttrack.c b/sys/contrib/dev/acpica/components/utilities/uttrack.c
index 2c60c1c7b1f1..362018ecf330 100644
--- a/sys/contrib/dev/acpica/components/utilities/uttrack.c
+++ b/sys/contrib/dev/acpica/components/utilities/uttrack.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/utilities/utuuid.c b/sys/contrib/dev/acpica/components/utilities/utuuid.c
index 669cce69b1f3..cc633e84aa47 100644
--- a/sys/contrib/dev/acpica/components/utilities/utuuid.c
+++ b/sys/contrib/dev/acpica/components/utilities/utuuid.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/utilities/utxface.c b/sys/contrib/dev/acpica/components/utilities/utxface.c
index 9b5f8b3c9d84..aee0a5559f4b 100644
--- a/sys/contrib/dev/acpica/components/utilities/utxface.c
+++ b/sys/contrib/dev/acpica/components/utilities/utxface.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/utilities/utxferror.c b/sys/contrib/dev/acpica/components/utilities/utxferror.c
index 08a3ab986c3f..1b5b0812ea14 100644
--- a/sys/contrib/dev/acpica/components/utilities/utxferror.c
+++ b/sys/contrib/dev/acpica/components/utilities/utxferror.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/utilities/utxfinit.c b/sys/contrib/dev/acpica/components/utilities/utxfinit.c
index f295471031d0..c1d23d4138c5 100644
--- a/sys/contrib/dev/acpica/components/utilities/utxfinit.c
+++ b/sys/contrib/dev/acpica/components/utilities/utxfinit.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/components/utilities/utxfmutex.c b/sys/contrib/dev/acpica/components/utilities/utxfmutex.c
index 595904977f23..7208ac78c76b 100644
--- a/sys/contrib/dev/acpica/components/utilities/utxfmutex.c
+++ b/sys/contrib/dev/acpica/components/utilities/utxfmutex.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/include/acapps.h b/sys/contrib/dev/acpica/include/acapps.h
index ccaea124afb1..be9bfdfc4857 100644
--- a/sys/contrib/dev/acpica/include/acapps.h
+++ b/sys/contrib/dev/acpica/include/acapps.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -159,7 +159,7 @@
/* Common info for tool signons */
#define ACPICA_NAME "Intel ACPI Component Architecture"
-#define ACPICA_COPYRIGHT "Copyright (c) 2000 - 2025 Intel Corporation"
+#define ACPICA_COPYRIGHT "Copyright (c) 2000 - 2026 Intel Corporation"
#if ACPI_MACHINE_WIDTH == 64
#define ACPI_WIDTH " (64-bit version)"
diff --git a/sys/contrib/dev/acpica/include/acbuffer.h b/sys/contrib/dev/acpica/include/acbuffer.h
index 682ddcd72625..2a88d9789c5f 100644
--- a/sys/contrib/dev/acpica/include/acbuffer.h
+++ b/sys/contrib/dev/acpica/include/acbuffer.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/include/acclib.h b/sys/contrib/dev/acpica/include/acclib.h
index 3960ffd2582e..d6c81823f354 100644
--- a/sys/contrib/dev/acpica/include/acclib.h
+++ b/sys/contrib/dev/acpica/include/acclib.h
@@ -9,7 +9,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/include/accommon.h b/sys/contrib/dev/acpica/include/accommon.h
index 10a39803842b..4ac4c0db87d7 100644
--- a/sys/contrib/dev/acpica/include/accommon.h
+++ b/sys/contrib/dev/acpica/include/accommon.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/include/acconfig.h b/sys/contrib/dev/acpica/include/acconfig.h
index 983dc3021185..e139f5837008 100644
--- a/sys/contrib/dev/acpica/include/acconfig.h
+++ b/sys/contrib/dev/acpica/include/acconfig.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/include/acconvert.h b/sys/contrib/dev/acpica/include/acconvert.h
index 9dedc51a7ef9..ac2e3f9c3a30 100644
--- a/sys/contrib/dev/acpica/include/acconvert.h
+++ b/sys/contrib/dev/acpica/include/acconvert.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/include/acdebug.h b/sys/contrib/dev/acpica/include/acdebug.h
index 63f39051a8ac..4a6b392d8d33 100644
--- a/sys/contrib/dev/acpica/include/acdebug.h
+++ b/sys/contrib/dev/acpica/include/acdebug.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/include/acdisasm.h b/sys/contrib/dev/acpica/include/acdisasm.h
index 29ce0d536df3..7f055125bbd3 100644
--- a/sys/contrib/dev/acpica/include/acdisasm.h
+++ b/sys/contrib/dev/acpica/include/acdisasm.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -467,6 +467,11 @@ extern ACPI_DMTABLE_INFO AcpiDmTableInfoDrtm0a[];
extern ACPI_DMTABLE_INFO AcpiDmTableInfoDrtm1[];
extern ACPI_DMTABLE_INFO AcpiDmTableInfoDrtm1a[];
extern ACPI_DMTABLE_INFO AcpiDmTableInfoDrtm2[];
+extern ACPI_DMTABLE_INFO AcpiDmTableInfoDtpr[];
+extern ACPI_DMTABLE_INFO AcpiDmTableInfoDtprInstance[];
+extern ACPI_DMTABLE_INFO AcpiDmTableInfoDtprArr[];
+extern ACPI_DMTABLE_INFO AcpiDmTableInfoDtprSerializeReq0[];
+extern ACPI_DMTABLE_INFO AcpiDmTableInfoDtprSerializeReq1[];
extern ACPI_DMTABLE_INFO AcpiDmTableInfoEcdt[];
extern ACPI_DMTABLE_INFO AcpiDmTableInfoEinj[];
extern ACPI_DMTABLE_INFO AcpiDmTableInfoEinj0[];
@@ -874,6 +879,10 @@ AcpiDmDumpDrtm (
ACPI_TABLE_HEADER *Table);
void
+AcpiDmDumpDtpr (
+ ACPI_TABLE_HEADER *Table);
+
+void
AcpiDmDumpEinj (
ACPI_TABLE_HEADER *Table);
diff --git a/sys/contrib/dev/acpica/include/acdispat.h b/sys/contrib/dev/acpica/include/acdispat.h
index 0573e5817dff..4d80aeba95cf 100644
--- a/sys/contrib/dev/acpica/include/acdispat.h
+++ b/sys/contrib/dev/acpica/include/acdispat.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/include/acevents.h b/sys/contrib/dev/acpica/include/acevents.h
index 22eff360559c..c765abf7ffb3 100644
--- a/sys/contrib/dev/acpica/include/acevents.h
+++ b/sys/contrib/dev/acpica/include/acevents.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/include/acexcep.h b/sys/contrib/dev/acpica/include/acexcep.h
index 7216e0d49148..643426fb47e6 100644
--- a/sys/contrib/dev/acpica/include/acexcep.h
+++ b/sys/contrib/dev/acpica/include/acexcep.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/include/acglobal.h b/sys/contrib/dev/acpica/include/acglobal.h
index 02167c3af092..b77f5a0d0444 100644
--- a/sys/contrib/dev/acpica/include/acglobal.h
+++ b/sys/contrib/dev/acpica/include/acglobal.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/include/achware.h b/sys/contrib/dev/acpica/include/achware.h
index 46efffb50708..fa20fcd8092d 100644
--- a/sys/contrib/dev/acpica/include/achware.h
+++ b/sys/contrib/dev/acpica/include/achware.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/include/acinterp.h b/sys/contrib/dev/acpica/include/acinterp.h
index b7f9e8f615e4..c0d372e52c64 100644
--- a/sys/contrib/dev/acpica/include/acinterp.h
+++ b/sys/contrib/dev/acpica/include/acinterp.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/include/aclocal.h b/sys/contrib/dev/acpica/include/aclocal.h
index ff18d617f79a..d9f126f0f6a1 100644
--- a/sys/contrib/dev/acpica/include/aclocal.h
+++ b/sys/contrib/dev/acpica/include/aclocal.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -332,6 +332,7 @@ typedef struct acpi_namespace_node
#define ANOBJ_IS_EXTERNAL 0x08 /* iASL only: This object created via External() */
#define ANOBJ_METHOD_NO_RETVAL 0x10 /* iASL only: Method has no return value */
#define ANOBJ_METHOD_SOME_NO_RETVAL 0x20 /* iASL only: Method has at least one return value */
+#define ANOBJ_IS_ALIAS 0x40 /* iASL only: Node is an alias to another node */
#define ANOBJ_IS_REFERENCED 0x80 /* iASL only: Object was referenced */
diff --git a/sys/contrib/dev/acpica/include/acmacros.h b/sys/contrib/dev/acpica/include/acmacros.h
index eabe403b3998..03ebb8848b5f 100644
--- a/sys/contrib/dev/acpica/include/acmacros.h
+++ b/sys/contrib/dev/acpica/include/acmacros.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/include/acnames.h b/sys/contrib/dev/acpica/include/acnames.h
index 070e318fb8cc..24915ab7c407 100644
--- a/sys/contrib/dev/acpica/include/acnames.h
+++ b/sys/contrib/dev/acpica/include/acnames.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/include/acnamesp.h b/sys/contrib/dev/acpica/include/acnamesp.h
index 41f704b3d74b..cc6b5989436f 100644
--- a/sys/contrib/dev/acpica/include/acnamesp.h
+++ b/sys/contrib/dev/acpica/include/acnamesp.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/include/acobject.h b/sys/contrib/dev/acpica/include/acobject.h
index 95be1a95b4c7..739b981b43e1 100644
--- a/sys/contrib/dev/acpica/include/acobject.h
+++ b/sys/contrib/dev/acpica/include/acobject.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/include/acopcode.h b/sys/contrib/dev/acpica/include/acopcode.h
index c8d17c3554d0..38e18f8593e4 100644
--- a/sys/contrib/dev/acpica/include/acopcode.h
+++ b/sys/contrib/dev/acpica/include/acopcode.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/include/acoutput.h b/sys/contrib/dev/acpica/include/acoutput.h
index 49a466dba33a..c0c37ef611f0 100644
--- a/sys/contrib/dev/acpica/include/acoutput.h
+++ b/sys/contrib/dev/acpica/include/acoutput.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/include/acparser.h b/sys/contrib/dev/acpica/include/acparser.h
index 8b3d3702f4a2..baf43876fb76 100644
--- a/sys/contrib/dev/acpica/include/acparser.h
+++ b/sys/contrib/dev/acpica/include/acparser.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/include/acpi.h b/sys/contrib/dev/acpica/include/acpi.h
index 07e5e93e2309..29081e0ef26e 100644
--- a/sys/contrib/dev/acpica/include/acpi.h
+++ b/sys/contrib/dev/acpica/include/acpi.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/include/acpiosxf.h b/sys/contrib/dev/acpica/include/acpiosxf.h
index 77a22eee7442..56112270b90e 100644
--- a/sys/contrib/dev/acpica/include/acpiosxf.h
+++ b/sys/contrib/dev/acpica/include/acpiosxf.h
@@ -10,7 +10,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/include/acpixf.h b/sys/contrib/dev/acpica/include/acpixf.h
index 00f0c08d4789..b19f7b334b5c 100644
--- a/sys/contrib/dev/acpica/include/acpixf.h
+++ b/sys/contrib/dev/acpica/include/acpixf.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -154,7 +154,7 @@
/* Current ACPICA subsystem version in YYYYMMDD format */
-#define ACPI_CA_VERSION 0x20251212
+#define ACPI_CA_VERSION 0x20260408
#include <contrib/dev/acpica/include/acconfig.h>
#include <contrib/dev/acpica/include/actypes.h>
diff --git a/sys/contrib/dev/acpica/include/acpredef.h b/sys/contrib/dev/acpica/include/acpredef.h
index 8cf6cf2dfcad..684c5a553e18 100644
--- a/sys/contrib/dev/acpica/include/acpredef.h
+++ b/sys/contrib/dev/acpica/include/acpredef.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -522,7 +522,7 @@ const ACPI_PREDEFINED_INFO AcpiGbl_PredefinedMethods[] =
{{"_CPC", METHOD_0ARGS,
METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Ints/Bufs) */
- PACKAGE_INFO (ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER | ACPI_RTYPE_BUFFER, 0,0,0,0),
+ PACKAGE_INFO (ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER | ACPI_RTYPE_BUFFER | ACPI_RTYPE_PACKAGE, 0,0,0,0),
{{"_CR3", METHOD_0ARGS, /* ACPI 6.0 */
METHOD_RETURNS (ACPI_RTYPE_INTEGER)}},
@@ -587,7 +587,7 @@ const ACPI_PREDEFINED_INFO AcpiGbl_PredefinedMethods[] =
METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Pkgs) each: 1 Buf, 1 Pkg */
PACKAGE_INFO (ACPI_PTYPE2_UUID_PAIR, ACPI_RTYPE_BUFFER, 1, ACPI_RTYPE_PACKAGE, 1,0),
- {{"_DSM", METHOD_4ARGS (ACPI_TYPE_BUFFER, ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER, ACPI_TYPE_ANY | ACPI_TYPE_PACKAGE) | ARG_COUNT_IS_MINIMUM,
+ {{"_DSM", METHOD_4ARGS (ACPI_TYPE_BUFFER, ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER, ACPI_TYPE_PACKAGE | ACPI_TYPE_ANY) | ARG_COUNT_IS_MINIMUM,
METHOD_RETURNS (ACPI_RTYPE_ALL)}}, /* Must return a value, but it can be of any type */
{{"_DSS", METHOD_1ARGS (ACPI_TYPE_INTEGER),
diff --git a/sys/contrib/dev/acpica/include/acresrc.h b/sys/contrib/dev/acpica/include/acresrc.h
index 2e3c7d3d1d40..781ecaa246d7 100644
--- a/sys/contrib/dev/acpica/include/acresrc.h
+++ b/sys/contrib/dev/acpica/include/acresrc.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/include/acrestyp.h b/sys/contrib/dev/acpica/include/acrestyp.h
index ab48a3911ae6..e9a20fa23e28 100644
--- a/sys/contrib/dev/acpica/include/acrestyp.h
+++ b/sys/contrib/dev/acpica/include/acrestyp.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -641,6 +641,7 @@ typedef struct acpi_resource_i2c_serialbus
UINT8 AccessMode;
UINT16 SlaveAddress;
UINT32 ConnectionSpeed;
+ UINT8 Lvr;
} ACPI_RESOURCE_I2C_SERIALBUS;
diff --git a/sys/contrib/dev/acpica/include/acstruct.h b/sys/contrib/dev/acpica/include/acstruct.h
index b1c54f09fe55..3c6ebfc2d179 100644
--- a/sys/contrib/dev/acpica/include/acstruct.h
+++ b/sys/contrib/dev/acpica/include/acstruct.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/include/actables.h b/sys/contrib/dev/acpica/include/actables.h
index 6f2cacbde3a1..edf3b80afc38 100644
--- a/sys/contrib/dev/acpica/include/actables.h
+++ b/sys/contrib/dev/acpica/include/actables.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/include/actbinfo.h b/sys/contrib/dev/acpica/include/actbinfo.h
index 0d80f67b6982..ff61c1861ee2 100644
--- a/sys/contrib/dev/acpica/include/actbinfo.h
+++ b/sys/contrib/dev/acpica/include/actbinfo.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -168,6 +168,7 @@
#define ACPI_DBGP_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_DBGP,f)
#define ACPI_DMAR_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_DMAR,f)
#define ACPI_DRTM_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_DRTM,f)
+#define ACPI_DTPR_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_DTPR,f)
#define ACPI_ECDT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_ECDT,f)
#define ACPI_EINJ_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_EINJ,f)
#define ACPI_ERDT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_ERDT,f)
@@ -284,6 +285,10 @@
#define ACPI_DRTM1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_DRTM_RESOURCE_LIST,f)
#define ACPI_DRTM1a_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_DRTM_RESOURCE,f)
#define ACPI_DRTM2_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_DRTM_DPS_ID,f)
+#define ACPI_DTPR_INST_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TPR_INSTANCE,f)
+#define ACPI_DTPR_ARR_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TPR_ARRAY,f)
+#define ACPI_DTPR_AUX_SR_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TPR_AUX_SR,f)
+#define ACPI_DTPR_SR_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TPR_SERIALIZE_REQUEST,f)
#define ACPI_EINJ0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_WHEA_HEADER,f)
#define ACPI_ERDT_HDR_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_SUBTBL_HDR_16,f)
#define ACPI_ERDT_CACD_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_ERDT_CACD,f)
@@ -496,6 +501,9 @@
#define ACPI_DMAR0_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_DMAR_HARDWARE_UNIT,f,o)
#define ACPI_DRTM_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_TABLE_DRTM,f,o)
#define ACPI_DRTM1a_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_DRTM_RESOURCE,f,o)
+#define ACPI_DTPR_BASE_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_TPRN_BASE_REG,f,o)
+#define ACPI_DTPR_LIM_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_TPRN_LIMIT_REG,f,o)
+#define ACPI_DTPR_SR_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_TPR_SERIALIZE_REQUEST,f,o)
#define ACPI_ERDT_RMDD_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_ERDT_RMDD,f,o)
#define ACPI_FADT_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_TABLE_FADT,f,o)
#define ACPI_FACS_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_TABLE_FACS,f,o)
diff --git a/sys/contrib/dev/acpica/include/actbl.h b/sys/contrib/dev/acpica/include/actbl.h
index ae52bd452c90..6e0ebda54e45 100644
--- a/sys/contrib/dev/acpica/include/actbl.h
+++ b/sys/contrib/dev/acpica/include/actbl.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/include/actbl1.h b/sys/contrib/dev/acpica/include/actbl1.h
index 6e7937999a5b..72a5c47d99c8 100644
--- a/sys/contrib/dev/acpica/include/actbl1.h
+++ b/sys/contrib/dev/acpica/include/actbl1.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -181,6 +181,7 @@
#define ACPI_SIG_DBGP "DBGP" /* Debug Port table */
#define ACPI_SIG_DMAR "DMAR" /* DMA Remapping table */
#define ACPI_SIG_DRTM "DRTM" /* Dynamic Root of Trust for Measurement table */
+#define ACPI_SIG_DTPR "DTPR" /* DMA TXT Protection Ranges table */
#define ACPI_SIG_ECDT "ECDT" /* Embedded Controller Boot Resources Table */
#define ACPI_SIG_EINJ "EINJ" /* Error Injection table */
#define ACPI_SIG_ERST "ERST" /* Error Record Serialization Table */
@@ -1344,6 +1345,291 @@ typedef struct acpi_drtm_dps_id
/*******************************************************************************
*
+ * DTPR - DMA TXT Protection Ranges Table
+ * Version 1
+ *
+ * Conforms to "Intel® Trusted Execution Technology (Intel® TXT) DMA Protection
+ * Ranges",
+ * Revision 0.73, August 2021
+ *
+ ******************************************************************************/
+
+typedef struct acpi_table_dtpr {
+ ACPI_TABLE_HEADER header;
+ UINT32 Flags; /* 36 */
+ UINT32 InsCnt;
+
+} ACPI_TABLE_DTPR;
+
+typedef struct acpi_tpr_array {
+ UINT64 Base;
+
+} ACPI_TPR_ARRAY;
+
+typedef struct acpi_tpr_instance {
+ UINT32 Flags;
+ UINT32 TprCnt;
+
+} ACPI_TPR_INSTANCE;
+
+typedef struct acpi_tpr_aux_sr {
+ UINT32 SrlCnt;
+
+} ACPI_TPR_AUX_SR;
+
+
+/*
+ * TPRn_BASE (ACPI_TPRN_BASE_REG)
+ *
+ * Specifies the start address of TPRn region. TPR region address and size must
+ * be with 1MB resolution. These bits are compared with the result of the
+ * TPRn_LIMIT[63:20], which is applied to the incoming address, to
+ * determine if an access fall within the TPRn defined region.
+ *
+ * Minimal TPRn_Base resolution is 1MB. Applied to the incoming address, to
+ * determine if an access fall within the TPRn defined region. Width is
+ * determined by a bus width which can be obtained via CPUID
+ * function 0x80000008.
+ */
+
+typedef UINT64 ACPI_TPRN_BASE_REG;
+
+
+/* TPRn_BASE Register Bit Masks */
+
+/* Bit 3 - RW: access: 1 == RO, 0 == RW register (for TPR must be RW) */
+#define ACPI_TPRN_BASE_RW_SHIFT 3
+
+
+#define ACPI_TPRN_BASE_RW_MASK ((UINT64) 1 << ACPI_TPRN_BASE_RW_SHIFT)
+
+
+/*
+ * Bit 4 - Enable: 0 – TPRn address range enabled;
+ * 1 – TPRn address range disabled.
+ */
+#define ACPI_TPRN_BASE_ENABLE_SHIFT 4
+
+
+#define ACPI_TPRN_BASE_ENABLE_MASK ((UINT64) 1 << ACPI_TPRN_BASE_ENABLE_SHIFT)
+
+
+/* Bits 63:20 - TprBaseRw */
+#define ACPI_TPRN_BASE_ADDR_SHIFT 20
+
+
+#define ACPI_TPRN_BASE_ADDR_MASK ((UINT64) 0xFFFFFFFFFFF << \
+ ACPI_TPRN_BASE_ADDR_SHIFT)
+
+
+/* TPRn_BASE Register Bit Handlers*/
+
+/*
+ * GET_TPRN_BASE_RW:
+ *
+ * Read RW bit from TPRn Base Register - bit 3.
+ *
+ * Input:
+ * - reg (represents TPRn Base Register (ACPI_TPRN_BASE_REG))
+ *
+ * Output:
+ *
+ * Returns RW bit value (UINT64).
+ */
+#define GET_TPRN_BASE_RW(reg) (((UINT64) reg & ACPI_TPRN_BASE_RW_MASK) >> \
+ ACPI_TPRN_BASE_RW_SHIFT)
+
+
+/*
+ * GET_TPRN_BASE_ENABLE:
+ *
+ * Read Enable bit from TPRn Base Register - bit 4.
+ *
+ * Input:
+ * - reg (represents TPRn Base Register (ACPI_TPRN_BASE_REG))
+ *
+ * Output:
+ *
+ * Returns Enable bit value (UINT64).
+ */
+#define GET_TPRN_BASE_ENABLE(reg) (((UINT64) reg & ACPI_TPRN_BASE_ENABLE_MASK) \
+ >> ACPI_TPRN_BASE_ENABLE_SHIFT)
+
+
+/*
+ * GET_TPRN_BASE_ADDR:
+ *
+ * Read TPRn Base Register address from bits 63:20.
+ *
+ * Input:
+ * - reg (represents TPRn Base Register (ACPI_TPRN_BASE_REG))
+ *
+ * Output:
+ *
+ * Returns TPRn Base Register address (UINT64).
+ */
+#define GET_TPRN_BASE_ADDR(reg) (((UINT64) reg & ACPI_TPRN_BASE_ADDR_MASK) \
+ >> ACPI_TPRN_BASE_ADDR_SHIFT)
+
+
+/*
+ * SET_TPRN_BASE_RW:
+ *
+ * Set RW bit in TPRn Base Register - bit 3.
+ *
+ * Input:
+ * - reg (represents TPRn Base Register (ACPI_TPRN_BASE_REG))
+ * - val (represents RW value to be set (UINT64))
+ */
+#define SET_TPRN_BASE_RW(reg, val) ACPI_REGISTER_INSERT_VALUE(reg, \
+ ACPI_TPRN_BASE_RW_SHIFT, \
+ ACPI_TPRN_BASE_RW_MASK, val);
+
+
+/*
+ * SET_TPRN_BASE_ENABLE:
+ *
+ * Set Enable bit in TPRn Base Register - bit 4.
+ *
+ * Input:
+ * - reg (represents TPRn Base Register (ACPI_TPRN_BASE_REG))
+ * - val (represents Enable value to be set (UINT64))
+ */
+#define SET_TPRN_BASE_ENABLE(reg, val) ACPI_REGISTER_INSERT_VALUE(reg, \
+ ACPI_TPRN_BASE_ENABLE_SHIFT, \
+ ACPI_TPRN_BASE_ENABLE_MASK, val);
+
+
+/*
+ * SET_TPRN_BASE_ADDR:
+ *
+ * Set TPRn Base Register address - bits 63:20
+ *
+ * Input
+ * - reg (represents TPRn Base Register (ACPI_TPRN_BASE_REG))
+ * - val (represents address value to be set (UINT64))
+ */
+#define SET_TPRN_BASE_ADDR(reg, val) ACPI_REGISTER_INSERT_VALUE(reg, \
+ ACPI_TPRN_BASE_ADDR_SHIFT, \
+ ACPI_TPRN_BASE_ADDR_MASK, val);
+
+
+/*
+ * TPRn_LIMIT
+ *
+ * This register defines an isolated region of memory that can be enabled
+ * to prohibit certain system agents from accessing memory. When an agent
+ * sends a request upstream, whether snooped or not, a TPR prevents that
+ * transaction from changing the state of memory.
+ *
+ * Minimal TPRn_Limit resolution is 1MB. Width is determined by a bus width.
+ */
+
+typedef UINT64 ACPI_TPRN_LIMIT_REG;
+
+
+/* TPRn_LIMIT Register Bit Masks */
+
+
+/* Bit 3 - RW: access: 1 == RO, 0 == RW register (for TPR must be RW) */
+#define ACPI_TPRN_LIMIT_RW_SHIFT 3
+
+
+#define ACPI_TPRN_LIMIT_RW_MASK ((UINT64) 1 << ACPI_TPRN_LIMIT_RW_SHIFT)
+
+
+/* Bits 63:20 - TprLimitRw */
+#define ACPI_TPRN_LIMIT_ADDR_SHIFT 20
+
+
+#define ACPI_TPRN_LIMIT_ADDR_MASK ((UINT64) 0xFFFFFFFFFFF << \
+ ACPI_TPRN_LIMIT_ADDR_SHIFT)
+
+
+/* TPRn_LIMIT Register Bit Handlers*/
+
+/*
+ * GET_TPRN_LIMIT_RW:
+ *
+ * Read RW bit from TPRn Limit Register - bit 3.
+ *
+ * Input:
+ * - reg (represents TPRn Limit Register (ACPI_TPRN_LIMIT_REG))
+ *
+ * Output:
+ *
+ * Returns RW bit value (UINT64).
+ */
+#define GET_TPRN_LIMIT_RW(reg) (((UINT64) reg & ACPI_TPRN_LIMIT_RW_MASK) \
+ >> ACPI_TPRN_LIMIT_RW_SHIFT)
+
+
+/*
+ * GET_TPRN_LIMIT_ADDR:
+ *
+ * Read TPRn Limit Register address from bits 63:20.
+ *
+ * Input:
+ * - reg (represents TPRn Limit Register (ACPI_TPRN_LIMIT_REG))
+ *
+ * Output:
+ *
+ * Returns TPRn Limit Register address (UINT64).
+ */
+#define GET_TPRN_LIMIT_ADDR(reg) (((UINT64) reg & ACPI_TPRN_LIMIT_ADDR_MASK) \
+ >> ACPI_TPRN_LIMIT_ADDR_SHIFT)
+
+
+/*
+ * SET_TPRN_LIMIT_RW:
+ *
+ * Set RW bit in TPRn Limit Register - bit 3.
+ *
+ * Input:
+ * - reg (represents TPRn Limit Register (ACPI_TPRN_LIMIT_REG))
+ * - val (represents RW value to be set (UINT64))
+ */
+#define SET_TPRN_LIMIT_RW(reg, val) ACPI_REGISTER_INSERT_VALUE(reg, \
+ ACPI_TPRN_LIMIT_RW_SHIFT, \
+ ACPI_TPRN_LIMIT_RW_MASK, val);
+
+
+/*
+ * SET_TPRN_LIMIT_ADDR:
+ *
+ * Set TPRn Limit Register address - bits 63:20.
+ *
+ * Input:
+ * - reg (represents TPRn Limit Register (ACPI_TPRN_LIMIT_REG))
+ * - val (represents address value to be set (UINT64))
+ */
+#define SET_TPRN_LIMIT_ADDR(reg, val) ACPI_REGISTER_INSERT_VALUE(reg, \
+ ACPI_TPRN_LIMIT_ADDR_SHIFT, \
+ ACPI_TPRN_LIMIT_ADDR_MASK, val);
+
+
+/*
+ * SERIALIZE_REQUEST
+ *
+ * This register is used to request serialization of non-coherent DMA
+ * transactions. OS shall issue it before changing of TPR settings
+ * (base / size).
+ */
+
+typedef struct acpi_tpr_serialize_request {
+ UINT64 SrRegister;
+ /*
+ * BIT 1 - Status of serialization request (RO)
+ * 0 == register idle, 1 == serialization in progress
+ * BIT 2 - Control field to initiate serialization (RW)
+ * 0 == normal, 1 == initialize serialization
+ * (self-clear to allow multiple serialization requests)
+ */
+} ACPI_TPR_SERIALIZE_REQUEST;
+
+
+/*******************************************************************************
+ *
* ECDT - Embedded Controller Boot Resources Table
* Version 1
*
@@ -2473,7 +2759,6 @@ typedef struct acpi_ibft_target
} ACPI_IBFT_TARGET;
-
/* Reset to default packing */
#pragma pack()
diff --git a/sys/contrib/dev/acpica/include/actbl2.h b/sys/contrib/dev/acpica/include/actbl2.h
index a51ff1ecaa09..a5e71e67285a 100644
--- a/sys/contrib/dev/acpica/include/actbl2.h
+++ b/sys/contrib/dev/acpica/include/actbl2.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/include/actbl3.h b/sys/contrib/dev/acpica/include/actbl3.h
index 6392359249c9..4886b12c0315 100644
--- a/sys/contrib/dev/acpica/include/actbl3.h
+++ b/sys/contrib/dev/acpica/include/actbl3.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/include/actypes.h b/sys/contrib/dev/acpica/include/actypes.h
index 3c95887b1678..38f3afa8c811 100644
--- a/sys/contrib/dev/acpica/include/actypes.h
+++ b/sys/contrib/dev/acpica/include/actypes.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/include/acutils.h b/sys/contrib/dev/acpica/include/acutils.h
index 06b8eb0bda6b..f306f93c1a9b 100644
--- a/sys/contrib/dev/acpica/include/acutils.h
+++ b/sys/contrib/dev/acpica/include/acutils.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/include/acuuid.h b/sys/contrib/dev/acpica/include/acuuid.h
index a950972b01b3..9546baa7f1de 100644
--- a/sys/contrib/dev/acpica/include/acuuid.h
+++ b/sys/contrib/dev/acpica/include/acuuid.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -205,6 +205,11 @@
#define UUID_CACHE_PROPERTIES "6DC63E77-257E-4E78-A973-A21F2796898D"
#define UUID_PHYSICAL_PROPERTY "DDE4D59A-AA42-4349-B407-EA40F57D9FB7"
+/* Modern Standby */
+#define UUID_LPS0_MICROSOFT "11E00D56-CE64-47CE-837B-1F898F9AA461"
+#define UUID_LPS0_INTEL "C4EB40A0-6CD2-11E2-BCFD-0800200C9A66"
+#define UUID_LPS0_AMD "E3F32452-FEBC-43CE-9039-932122D37721"
+
/* Miscellaneous */
#define UUID_PLATFORM_CAPABILITIES "0811b06e-4a27-44f9-8d60-3cbbc22e7b48"
diff --git a/sys/contrib/dev/acpica/include/amlcode.h b/sys/contrib/dev/acpica/include/amlcode.h
index 6bb591904794..ffd48e9e6751 100644
--- a/sys/contrib/dev/acpica/include/amlcode.h
+++ b/sys/contrib/dev/acpica/include/amlcode.h
@@ -10,7 +10,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/include/amlresrc.h b/sys/contrib/dev/acpica/include/amlresrc.h
index 4482ed378ab1..3362b52b3205 100644
--- a/sys/contrib/dev/acpica/include/amlresrc.h
+++ b/sys/contrib/dev/acpica/include/amlresrc.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/include/platform/acenv.h b/sys/contrib/dev/acpica/include/platform/acenv.h
index b842965bfca0..8b821f176309 100644
--- a/sys/contrib/dev/acpica/include/platform/acenv.h
+++ b/sys/contrib/dev/acpica/include/platform/acenv.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/include/platform/acenvex.h b/sys/contrib/dev/acpica/include/platform/acenvex.h
index e9632619abf5..2735e02174de 100644
--- a/sys/contrib/dev/acpica/include/platform/acenvex.h
+++ b/sys/contrib/dev/acpica/include/platform/acenvex.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/include/platform/acfreebsd.h b/sys/contrib/dev/acpica/include/platform/acfreebsd.h
index b537a25f9fbd..c039ba1c2ded 100644
--- a/sys/contrib/dev/acpica/include/platform/acfreebsd.h
+++ b/sys/contrib/dev/acpica/include/platform/acfreebsd.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/include/platform/acgcc.h b/sys/contrib/dev/acpica/include/platform/acgcc.h
index 39ff864fa5d7..9ed3be2b0658 100644
--- a/sys/contrib/dev/acpica/include/platform/acgcc.h
+++ b/sys/contrib/dev/acpica/include/platform/acgcc.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/include/platform/acgccex.h b/sys/contrib/dev/acpica/include/platform/acgccex.h
index bb3b55cf2ca6..fae2413bf712 100644
--- a/sys/contrib/dev/acpica/include/platform/acgccex.h
+++ b/sys/contrib/dev/acpica/include/platform/acgccex.h
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/os_specific/service_layers/osgendbg.c b/sys/contrib/dev/acpica/os_specific/service_layers/osgendbg.c
index eb34274ce670..854a8509fb85 100644
--- a/sys/contrib/dev/acpica/os_specific/service_layers/osgendbg.c
+++ b/sys/contrib/dev/acpica/os_specific/service_layers/osgendbg.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/contrib/dev/acpica/os_specific/service_layers/osunixxf.c b/sys/contrib/dev/acpica/os_specific/service_layers/osunixxf.c
index 81cda5e4eb65..0a1a0c0bf9d9 100644
--- a/sys/contrib/dev/acpica/os_specific/service_layers/osunixxf.c
+++ b/sys/contrib/dev/acpica/os_specific/service_layers/osunixxf.c
@@ -8,7 +8,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
* All rights reserved.
*
* 2. License
diff --git a/sys/dev/acpi_support/acpi_ibm.c b/sys/dev/acpi_support/acpi_ibm.c
index 1221384e7d8a..2967832a0878 100644
--- a/sys/dev/acpi_support/acpi_ibm.c
+++ b/sys/dev/acpi_support/acpi_ibm.c
@@ -1453,7 +1453,7 @@ acpi_ibm_eventhandler(struct acpi_ibm_softc *sc, int arg)
* instead of suspend-to-RAM.
*/
case IBM_EVENT_SUSPEND_TO_RAM:
- power_pm_suspend(POWER_SSTATE_TRANSITION_SUSPEND);
+ power_pm_suspend(POWER_TRANSITION_SUSPEND);
break;
case IBM_EVENT_BLUETOOTH:
diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
index bdc197a4fb59..ec1f002150c1 100644
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -672,12 +672,12 @@ acpi_attach(device_t dev)
* s2idle when ACPI_FADT_LOW_POWER_S0 is set.
*/
sc->acpi_sleep_button_stype = POWER_STYPE_UNKNOWN;
- for (stype = POWER_STYPE_STANDBY; stype <= POWER_STYPE_HIBERNATE; stype++)
+ for (stype = POWER_STYPE_STANDBY; stype <= POWER_STYPE_FW_HIBERNATE; stype++)
if (acpi_supported_stypes[stype]) {
sc->acpi_sleep_button_stype = stype;
break;
}
- if (sc->acpi_sleep_button_stype == POWER_STYPE_HIBERNATE ||
+ if (sc->acpi_sleep_button_stype == POWER_STYPE_FW_HIBERNATE ||
sc->acpi_sleep_button_stype == POWER_STYPE_UNKNOWN) {
if (acpi_supported_stypes[POWER_STYPE_SUSPEND_TO_IDLE])
sc->acpi_sleep_button_stype = POWER_STYPE_SUSPEND_TO_IDLE;
@@ -816,9 +816,9 @@ acpi_stype_to_sstate(struct acpi_softc *sc, enum power_stype stype)
return (ACPI_STATE_S0);
case POWER_STYPE_STANDBY:
return (sc->acpi_standby_sx);
- case POWER_STYPE_SUSPEND_TO_MEM:
+ case POWER_STYPE_FW_SUSPEND:
return (ACPI_STATE_S3);
- case POWER_STYPE_HIBERNATE:
+ case POWER_STYPE_FW_HIBERNATE:
return (ACPI_STATE_S4);
case POWER_STYPE_POWEROFF:
return (ACPI_STATE_S5);
@@ -851,9 +851,9 @@ acpi_sstate_to_stype(int sstate)
case ACPI_STATE_S2:
return (POWER_STYPE_STANDBY);
case ACPI_STATE_S3:
- return (POWER_STYPE_SUSPEND_TO_MEM);
+ return (POWER_STYPE_FW_SUSPEND);
case ACPI_STATE_S4:
- return (POWER_STYPE_HIBERNATE);
+ return (POWER_STYPE_FW_HIBERNATE);
case ACPI_STATE_S5:
return (POWER_STYPE_POWEROFF);
}
@@ -3723,8 +3723,8 @@ acpi_EnterSleepState(struct acpi_softc *sc, enum power_stype stype)
case POWER_STYPE_STANDBY:
do_standby(sc, &slp_state, intr);
break;
- case POWER_STYPE_SUSPEND_TO_MEM:
- case POWER_STYPE_HIBERNATE:
+ case POWER_STYPE_FW_SUSPEND:
+ case POWER_STYPE_FW_HIBERNATE:
do_sleep(sc, &slp_state, intr, acpi_sstate);
break;
case POWER_STYPE_SUSPEND_TO_IDLE:
diff --git a/sys/dev/cxgbe/common/t4_regs.h b/sys/dev/cxgbe/common/t4_regs.h
index 09d0d4aa2c08..9984461352d0 100644
--- a/sys/dev/cxgbe/common/t4_regs.h
+++ b/sys/dev/cxgbe/common/t4_regs.h
@@ -1465,10 +1465,10 @@
#define A_SGE_INT_ENABLE3 0x1040
#define A_SGE_FL_BUFFER_SIZE0 0x1044
-#define S_SIZE 4
+#define CXGBE_S_SIZE 4
#define CXGBE_M_SIZE 0xfffffffU
-#define V_SIZE(x) ((x) << S_SIZE)
-#define G_SIZE(x) (((x) >> S_SIZE) & CXGBE_M_SIZE)
+#define CXGBE_V_SIZE(x) ((x) << S_SIZE)
+#define CXGBE_G_SIZE(x) (((x) >> S_SIZE) & CXGBE_M_SIZE)
#define S_T6_SIZE 4
#define M_T6_SIZE 0xfffffU
@@ -26578,15 +26578,10 @@
#define V_CIM_ULP_TX_PKT_ERR_CODE(x) ((x) << S_CIM_ULP_TX_PKT_ERR_CODE)
#define G_CIM_ULP_TX_PKT_ERR_CODE(x) (((x) >> S_CIM_ULP_TX_PKT_ERR_CODE) & M_CIM_ULP_TX_PKT_ERR_CODE)
-#define S_CIM_SGE1_PKT_ERR_CODE 8
-#define M_CIM_SGE1_PKT_ERR_CODE 0xffU
-#define V_CIM_SGE1_PKT_ERR_CODE(x) ((x) << S_CIM_SGE1_PKT_ERR_CODE)
-#define G_CIM_SGE1_PKT_ERR_CODE(x) (((x) >> S_CIM_SGE1_PKT_ERR_CODE) & M_CIM_SGE1_PKT_ERR_CODE)
-
-#define S_CIM_SGE0_PKT_ERR_CODE 0
-#define M_CIM_SGE0_PKT_ERR_CODE 0xffU
-#define V_CIM_SGE0_PKT_ERR_CODE(x) ((x) << S_CIM_SGE0_PKT_ERR_CODE)
-#define G_CIM_SGE0_PKT_ERR_CODE(x) (((x) >> S_CIM_SGE0_PKT_ERR_CODE) & M_CIM_SGE0_PKT_ERR_CODE)
+#define S_CIM_SGE_PKT_ERR_CODE 0
+#define M_CIM_SGE_PKT_ERR_CODE 0xffU
+#define V_CIM_SGE_PKT_ERR_CODE(x) ((x) << S_CIM_SGE_PKT_ERR_CODE)
+#define G_CIM_SGE_PKT_ERR_CODE(x) (((x) >> S_CIM_SGE_PKT_ERR_CODE) & M_CIM_SGE_PKT_ERR_CODE)
#define S_CIM_PCIE_PKT_ERR_CODE 8
#define M_CIM_PCIE_PKT_ERR_CODE 0xffU
@@ -60550,17 +60545,15 @@
#define A_MAC_PORT_PTP_DRIFT_ADJUST_COUNT 0x9a0
#define A_MAC_PORT_PTP_OFFSET_ADJUST_FINE 0x9a4
-#if 0
-#define S_B 16
-#define M_B 0xffffU
-#define V_B(x) ((x) << S_B)
-#define G_B(x) (((x) >> S_B) & M_B)
-#endif
+#define CXGBE_S_B 16
+#define CXGBE_M_B 0xffffU
+#define CXGBE_V_B(x) ((x) << CXGBE_S_B)
+#define CXGBE_G_B(x) (((x) >> CXGBE_S_B) & CXGBE_M_B)
-#define S_A 0
-#define M_A 0xffffU
-#define V_A(x) ((x) << S_A)
-#define G_A(x) (((x) >> S_A) & M_A)
+#define CXGBE_S_A 0
+#define CXGBE_M_A 0xffffU
+#define CXGBE_V_A(x) ((x) << CXGBE_S_A)
+#define CXGBE_G_A(x) (((x) >> CXGBE_S_A) & CXGBE_M_A)
#define A_MAC_PORT_PTP_OFFSET_ADJUST_TOTAL 0x9a8
#define A_MAC_PORT_PTP_CFG 0x9ac
@@ -62257,10 +62250,10 @@
#define A_MAC_PORT_MTIP_VLAN_TPID_0 0x1a00
-#define S_VLANTAG 0
+#define CXGBE_S_VLANTAG 0
#define CXGBE_M_VLANTAG 0xffffU
-#define V_VLANTAG(x) ((x) << S_VLANTAG)
-#define G_VLANTAG(x) (((x) >> S_VLANTAG) & M_VLANTAG)
+#define CXGBE_V_VLANTAG(x) ((x) << CXGBE_S_VLANTAG)
+#define CXGBE_G_VLANTAG(x) (((x) >> CXGBE_S_VLANTAG) & CXGBE_M_VLANTAG)
#define A_MAC_PORT_MTIP_VLAN_TPID_1 0x1a04
#define A_MAC_PORT_MTIP_VLAN_TPID_2 0x1a08
@@ -69613,10 +69606,10 @@
#define V_INIT_ENABLE(x) ((x) << S_INIT_ENABLE)
#define F_INIT_ENABLE V_INIT_ENABLE(1U)
-#define S_WAIT 16
-#define M_WAIT 0xfffU
-#define CXGBE_V_WAIT(x) ((x) << S_WAIT)
-#define G_WAIT(x) (((x) >> S_WAIT) & M_WAIT)
+#define CXGBE_S_WAIT 16
+#define CXGBE_M_WAIT 0xfffU
+#define CXGBE_V_WAIT(x) ((x) << CXGBE_S_WAIT)
+#define CXGBE_G_WAIT(x) (((x) >> CXGBE_S_WAIT) & CXGBE_M_WAIT)
#define S_EN_MULTI_RANK_SEL 4
#define V_EN_MULTI_RANK_SEL(x) ((x) << S_EN_MULTI_RANK_SEL)
diff --git a/sys/dev/cxgbe/firmware/t4fw_interface.h b/sys/dev/cxgbe/firmware/t4fw_interface.h
index b11552dce021..6235a2c3fab4 100644
--- a/sys/dev/cxgbe/firmware/t4fw_interface.h
+++ b/sys/dev/cxgbe/firmware/t4fw_interface.h
@@ -2560,6 +2560,22 @@ struct fw_ri_wr {
__be32 tpt_offset_t10_config;
__be32 r8[2];
} nvmet_init;
+ struct fw_ri_iscsi_init {
+ __u8 type;
+ __u8 dcrc_dis_to_hcrc;
+ __u8 r4[3];
+ __u8 qp_caps;
+ __be16 r5;
+ __be32 pdid;
+ __be32 qpid;
+ __be32 sq_eqid;
+ __be32 r6;
+ __be32 scqid;
+ __be32 rcqid;
+ __be32 r7[4];
+ __be32 r8[2];
+ __be64 r9;
+ } iscsi_init;
struct fw_ri_fini {
__u8 type;
__u8 r3[7];
@@ -2634,6 +2650,37 @@ struct fw_ri_wr {
#define G_FW_RI_WR_T10_CONFIG(x) \
(((x) >> S_FW_RI_WR_T10_CONFIG) & M_FW_RI_WR_T10_CONFIG)
+#define S_FW_RI_WR_DCRC_DIS 7
+#define M_FW_RI_WR_DCRC_DIS 0x1
+#define V_FW_RI_WR_DCRC_DIS(x) ((x) << S_FW_RI_WR_DCRC_DIS)
+#define G_FW_RI_WR_DCRC_DIS(x) \
+ (((x) >> S_FW_RI_WR_DCRC_DIS) & M_FW_RI_WR_DCRC_DIS)
+#define F_FW_RI_WR_DCRC_DIS V_FW_RI_WR_DCRC_DIS(1U)
+
+#define S_FW_RI_WR_HCRC_DIS 6
+#define M_FW_RI_WR_HCRC_DIS 0x1
+#define V_FW_RI_WR_HCRC_DIS(x) ((x) << S_FW_RI_WR_HCRC_DIS)
+#define G_FW_RI_WR_HCRC_DIS(x) \
+ (((x) >> S_FW_RI_WR_HCRC_DIS) & M_FW_RI_WR_HCRC_DIS)
+#define F_FW_RI_WR_HCRC_DIS V_FW_RI_WR_HCRC_DIS(1U)
+
+#define S_FW_RI_WR_PSZ_IDX 4
+#define M_FW_RI_WR_PSZ_IDX 0x3
+#define V_FW_RI_WR_PSZ_IDX(x) ((x) << S_FW_RI_WR_PSZ_IDX)
+#define G_FW_RI_WR_PSZ_IDX(x) \
+ (((x) >> S_FW_RI_WR_PSZ_IDX) & M_FW_RI_WR_PSZ_IDX)
+
+#define S_FW_RI_WR_DCRC 1
+#define M_FW_RI_WR_DCRC 0x1
+#define V_FW_RI_WR_DCRC(x) ((x) << S_FW_RI_WR_DCRC)
+#define G_FW_RI_WR_DCRC(x) (((x) >> S_FW_RI_WR_DCRC) & M_FW_RI_WR_DCRC)
+#define F_FW_RI_WR_DCRC V_FW_RI_WR_DCRC(1U)
+
+#define S_FW_RI_WR_HCRC 0
+#define M_FW_RI_WR_HCRC 0x1
+#define V_FW_RI_WR_HCRC(x) ((x) << S_FW_RI_WR_HCRC)
+#define G_FW_RI_WR_HCRC(x) (((x) >> S_FW_RI_WR_HCRC) & M_FW_RI_WR_HCRC)
+#define F_FW_RI_WR_HCRC V_FW_RI_WR_HCRC(1U)
/******************************************************************************
* R o C E V 2 W O R K R E Q U E S T s
@@ -2951,6 +2998,24 @@ struct fw_v2_nvmet_tx_data_wr {
#endif
};
+#define S_FW_V2_NVMET_TX_DATA_WR_DACK_CHANGE 20
+#define M_FW_V2_NVMET_TX_DATA_WR_DACK_CHANGE 0x1
+#define V_FW_V2_NVMET_TX_DATA_WR_DACK_CHANGE(x) \
+ ((x) << S_FW_V2_NVMET_TX_DATA_WR_DACK_CHANGE)
+#define G_FW_V2_NVMET_TX_DATA_WR_DACK_CHANGE(x) \
+ (((x) >> S_FW_V2_NVMET_TX_DATA_WR_DACK_CHANGE) & \
+ M_FW_V2_NVMET_TX_DATA_WR_DACK_CHANGE)
+#define F_FW_V2_NVMET_TX_DATA_WR_DACK_CHANGE \
+ V_FW_V2_NVMET_TX_DATA_WR_DACK_CHANGE(1U)
+
+#define S_FW_V2_NVMET_TX_DATA_WR_DACK_MODE 18
+#define M_FW_V2_NVMET_TX_DATA_WR_DACK_MODE 0x3
+#define V_FW_V2_NVMET_TX_DATA_WR_DACK_MODE(x) \
+ ((x) << S_FW_V2_NVMET_TX_DATA_WR_DACK_MODE)
+#define G_FW_V2_NVMET_TX_DATA_WR_DACK_MODE(x) \
+ (((x) >> S_FW_V2_NVMET_TX_DATA_WR_DACK_MODE) & \
+ M_FW_V2_NVMET_TX_DATA_WR_DACK_MODE)
+
#define S_FW_V2_NVMET_TX_DATA_WR_FLAGS_HI 10
#define M_FW_V2_NVMET_TX_DATA_WR_FLAGS_HI 0x3fffff
#define V_FW_V2_NVMET_TX_DATA_WR_FLAGS_HI(x) \
@@ -4990,6 +5055,16 @@ struct fw_crypto_update_sa_wr {
} key;
};
+#define S_FW_CRYPTO_UPDATE_SA_WR_EG_IPVER 3
+#define M_FW_CRYPTO_UPDATE_SA_WR_EG_IPVER 0x1
+#define V_FW_CRYPTO_UPDATE_SA_WR_EG_IPVER(x) \
+ ((x) << S_FW_CRYPTO_UPDATE_SA_WR_EG_IPVER)
+#define G_FW_CRYPTO_UPDATE_SA_WR_EG_IPVER(x) \
+ (((x) >> S_FW_CRYPTO_UPDATE_SA_WR_EG_IPVER) & \
+ M_FW_CRYPTO_UPDATE_SA_WR_EG_IPVER)
+#define F_FW_CRYPTO_UPDATE_SA_WR_EG_IPVER \
+ V_FW_CRYPTO_UPDATE_SA_WR_EG_IPVER(1U)
+
#define S_FW_CRYPTO_UPDATE_SA_WR_SAOP 2
#define M_FW_CRYPTO_UPDATE_SA_WR_SAOP 0x1
#define V_FW_CRYPTO_UPDATE_SA_WR_SAOP(x) \
@@ -8952,24 +9027,40 @@ enum fw_port_type {
FW_PORT_TYPE_KX4 = 5, /* No, 4, No, No, Yes, Yes, 10G */
FW_PORT_TYPE_CX4 = 6, /* No, 4, No, No, No, No, 10G */
FW_PORT_TYPE_KX = 7, /* No, 1, No, No, Yes, No, 1G */
- FW_PORT_TYPE_KR = 8, /* No, 1, No, No, Yes, Yes, 10G */
+ FW_PORT_TYPE_KR = 8, /* No, 1, No, No, Yes, Yes, 10G BP AN */
FW_PORT_TYPE_SFP = 9, /* No, 1, Yes, No, No, No, 10G */
- FW_PORT_TYPE_BP_AP = 10, /* No, 1, No, No, Yes, Yes, 10G, BP ANGE */
- FW_PORT_TYPE_BP4_AP = 11, /* No, 4, No, No, Yes, Yes, 10G, BP ANGE */
+ FW_PORT_TYPE_BP_AP = 10, /* No, 1, No, No, Yes, Yes, 10G, BP AN */
+ FW_PORT_TYPE_BP4_AP = 11, /* No, 4, No, No, Yes, Yes, 10G, BP AN */
FW_PORT_TYPE_QSFP_10G = 12, /* No, 1, Yes, No, No, No, 10G */
FW_PORT_TYPE_QSA = 13, /* No, 1, Yes, No, No, No, 10G */
FW_PORT_TYPE_QSFP = 14, /* No, 4, Yes, No, No, No, 40G */
- FW_PORT_TYPE_BP40_BA = 15, /* No, 4, No, No, Yes, Yes, 40G/10G/1G, BP ANGE */
- FW_PORT_TYPE_KR4_100G = 16, /* No, 4, 100G/40G/25G, Backplane */
+ FW_PORT_TYPE_BP40_BA = 15, /* No, 4, No, No, Yes, Yes, 40G/10G/1G, BP AN */
+ FW_PORT_TYPE_KR4_100G = 16, /* No, 4, 100G/40G/50G/25G/10G/1G, BP AN */
FW_PORT_TYPE_CR4_QSFP = 17, /* No, 4, 100G/40G/25G */
- FW_PORT_TYPE_CR_QSFP = 18, /* No, 1, 25G Spider cable */
- FW_PORT_TYPE_CR2_QSFP = 19, /* No, 2, 50G */
+ FW_PORT_TYPE_CR_QSFP = 18, /* No, 1, 25G, Spider cable */
+ FW_PORT_TYPE_CR2_QSFP = 19, /* No, 2, 50G, Spider cable */
FW_PORT_TYPE_SFP28 = 20, /* No, 1, 25G/10G/1G */
FW_PORT_TYPE_KR_SFP28 = 21, /* No, 1, 25G/10G/1G using Backplane */
FW_PORT_TYPE_KR_XLAUI = 22, /* No, 4, 40G/10G/1G, No AN*/
+ FW_PORT_TYPE_BARE_LINK_50G = 23, /* No, 1, 50G */
+ FW_PORT_TYPE_BARE_LINK_100G = 24, /* No, 2, 100G/50G */
+ FW_PORT_TYPE_BARE_LINK_200G = 25, /* No, 4, 200G/100G/50G */
FW_PORT_TYPE_SFP56 = 26, /* No, 1, 50G/25G */
FW_PORT_TYPE_QSFP56 = 27, /* No, 4, 200G/100G/50G/25G */
- FW_PORT_TYPE_QSFPDD = 34, /* No, 8, 400G/200G/100G/50G */
+ FW_PORT_TYPE_QSFP56_4_50G = 28, /* No, 1, 50G, Spider cable */
+ FW_PORT_TYPE_KR_50G = 29, /* No, 1, 50G/25G/10G/1G, BP AN */
+ FW_PORT_TYPE_KR2_100G = 30, /* No, 2, 100G/50G/25G/10G/1G, BP AN */
+ FW_PORT_TYPE_KR4_200G = 31, /* No, 4, 200G/100G/40G/50G/25G/10G/1G, BP AN */
+ FW_PORT_TYPE_QSFP56_2_50G = 32, /* No, 1, 50G, Spider cable */
+ FW_PORT_TYPE_OSFP = 33, /* No, 8, 400G/200G/100G/50G */
+ FW_PORT_TYPE_QSFPDD = 34, /* No, 8, 400G/200G/100G/50G */
+ FW_PORT_TYPE_OSFP_2_200G = 35, /* No, 4, 200G, Spider cable */
+ FW_PORT_TYPE_QSFPDD_2_200G = 36,/* No, 4, 200G, Spider cable */
+ FW_PORT_TYPE_KR8_400G = 37, /* No, 8, 400G/200G/100G/50G/40G/25G/10G/1G, BP AN */
+ FW_PORT_TYPE_QSFP56_2_100G = 38,/* No, 2, 100G, Spider cable */
+ FW_PORT_TYPE_QSFPDD_4_100G = 39,/* No, 2, 100G, Spider cable */
+ FW_PORT_TYPE_KR2_50G = 40, /* No, 1, 50G/25G/10G/1G, BP AN */
+ FW_PORT_TYPE_MAX,
FW_PORT_TYPE_NONE = M_FW_PORT_CMD_PORTTYPE32
};
diff --git a/sys/dev/cxgbe/firmware/t7fw_cfg.txt b/sys/dev/cxgbe/firmware/t7fw_cfg.txt
index 70b05da04a23..33c703fdc9d7 100644
--- a/sys/dev/cxgbe/firmware/t7fw_cfg.txt
+++ b/sys/dev/cxgbe/firmware/t7fw_cfg.txt
@@ -175,6 +175,11 @@
# TPT error.
# Err2uP = 0
+ # ULP_TX_ACCELERATOR_CTL
+ reg[0x8f90] = 0x00000015/0x00000015 # Compression block clock gating
+ # Dedupe clock gating
+ # Erasure Coding clock gating
+
#ULP_RX_CTL1
reg[0x19330] = 0x000000f0/0x000000f0 # RDMA_Invld_Msg_Dis = 3
# ROCE_Invld_Msg_Dis = 3
@@ -201,7 +206,7 @@
# default gc enabled.
# HMA configuration (uncomment following lines to enable HMA)
- hma_size = 128 # Size (in MBs) of host memory expected
+ hma_size = 256 # Size (in MBs) of host memory expected
hma_regions = iscsi,rrq,tls,ddp,pmrx,stag,pbl,rq # What all regions to place in host memory
#mc[0]=0
@@ -394,8 +399,7 @@
neq = 16 # niqflint + nethctrl Egress Queues
nexactf = 8 # number of exact MPSTCAM MAC filters
cmask = all # access to all channels
- #pmask = 0x4 # access to only one port
- pmask = 0x1 # access to only one port
+ pmask = 0x4 # access to only one port
[function "3"]
nvf = 16 # NVF on this function
@@ -407,7 +411,7 @@
neq = 16 # niqflint + nethctrl Egress Queues
nexactf = 8 # number of exact MPSTCAM MAC filters
cmask = all # access to all channels
- #pmask = 0x2 # access to only one port
+ pmask = 0x8 # access to only one port
# Some OS Drivers manage all application functions for all ports via PF4.
# Thus we need to provide a large number of resources here. For Egress
@@ -421,7 +425,7 @@
r_caps = all # read permissions for all commands
nvi = 28 # NVI_UNIFIED
niqflint = 170 # NFLIQ_UNIFIED + NLFIQ_WD
- nethctrl = 224 # NETHCTRL_UNIFIED + NETHCTRL_WD
+ nethctrl = 288 # NETHCTRL_UNIFIED + NETHCTRL_WD
neq = 252 # NEQ_UNIFIED + NEQ_WD
nqpcq = 12288
nexactf = 40 # NMPSTCAM_UNIFIED
@@ -435,8 +439,7 @@
nserver = 480 # number of server region entries
nhash = 12288 # number of hash region entries
nhpfilter = 64 # number of high priority filter region entries
- #protocol = nic_vm, ofld, rddp, rdmac, iscsi_initiator_pdu, iscsi_target_pdu, iscsi_t10dif, tlskeys, crypto_lookaside, ipsec_inline, rocev2, nic_hashfilter, ofld_sendpath
- protocol = nic_vm, ofld, rddp, rdmac, iscsi_initiator_pdu, iscsi_target_pdu, iscsi_t10dif, tlskeys, crypto_lookaside, ipsec_inline, rocev2, nic_hashfilter, nvme_tcp
+ protocol = nic_vm, ofld, rddp, rdmac, iscsi_initiator_pdu, iscsi_target_pdu, iscsi_t10dif, tlskeys, crypto_lookaside, ipsec_inline, rocev2, nic_hashfilter, nvme_tcp, ofld_sendpath
tp_l2t = 3072
tp_ddp = 2
tp_ddp_iscsi = 2
@@ -643,7 +646,7 @@
[fini]
version = 0x1425001d
- checksum = 0x3671da3b
+ checksum = 0x2419f987
# Total resources used by above allocations:
# Virtual Interfaces: 104
diff --git a/sys/dev/cxgbe/firmware/t7fw_cfg_uwire.txt b/sys/dev/cxgbe/firmware/t7fw_cfg_uwire.txt
index b1f5129238eb..9da841153138 100644
--- a/sys/dev/cxgbe/firmware/t7fw_cfg_uwire.txt
+++ b/sys/dev/cxgbe/firmware/t7fw_cfg_uwire.txt
@@ -175,6 +175,11 @@
# TPT error.
# Err2uP = 0
+ # ULP_TX_ACCELERATOR_CTL
+ reg[0x8f90] = 0x00000015/0x00000015 # Compression block clock gating
+ # Dedupe clock gating
+ # Erasure Coding clock gating
+
#ULP_RX_CTL1
reg[0x19330] = 0x000000f0/0x000000f0 # RDMA_Invld_Msg_Dis = 3
# ROCE_Invld_Msg_Dis = 3
@@ -201,7 +206,7 @@
# default gc enabled.
# HMA configuration (uncomment following lines to enable HMA)
- hma_size = 128 # Size (in MBs) of host memory expected
+ hma_size = 256 # Size (in MBs) of host memory expected
hma_regions = iscsi,rrq,tls,ddp,pmrx,stag,pbl,rq # What all regions to place in host memory
#mc[0]=0
@@ -394,8 +399,7 @@
neq = 16 # niqflint + nethctrl Egress Queues
nexactf = 8 # number of exact MPSTCAM MAC filters
cmask = all # access to all channels
- #pmask = 0x4 # access to only one port
- pmask = 0x1 # access to only one port
+ pmask = 0x4 # access to only one port
[function "3"]
nvf = 16 # NVF on this function
@@ -407,7 +411,7 @@
neq = 16 # niqflint + nethctrl Egress Queues
nexactf = 8 # number of exact MPSTCAM MAC filters
cmask = all # access to all channels
- #pmask = 0x2 # access to only one port
+ pmask = 0x8 # access to only one port
# Some OS Drivers manage all application functions for all ports via PF4.
# Thus we need to provide a large number of resources here. For Egress
@@ -421,7 +425,7 @@
r_caps = all # read permissions for all commands
nvi = 28 # NVI_UNIFIED
niqflint = 170 # NFLIQ_UNIFIED + NLFIQ_WD
- nethctrl = 224 # NETHCTRL_UNIFIED + NETHCTRL_WD
+ nethctrl = 288 # NETHCTRL_UNIFIED + NETHCTRL_WD
neq = 252 # NEQ_UNIFIED + NEQ_WD
nqpcq = 12288
nexactf = 40 # NMPSTCAM_UNIFIED
@@ -435,8 +439,7 @@
nserver = 480 # number of server region entries
nhash = 12288 # number of hash region entries
nhpfilter = 64 # number of high priority filter region entries
- #protocol = nic_vm, ofld, rddp, rdmac, iscsi_initiator_pdu, iscsi_target_pdu, iscsi_t10dif, tlskeys, crypto_lookaside, ipsec_inline, rocev2, nic_hashfilter, ofld_sendpath
- protocol = nic_vm, ofld, rddp, rdmac, iscsi_initiator_pdu, iscsi_target_pdu, iscsi_t10dif, tlskeys, crypto_lookaside, ipsec_inline, rocev2, nic_hashfilter, nvme_tcp
+ protocol = nic_vm, ofld, rddp, rdmac, iscsi_initiator_pdu, iscsi_target_pdu, iscsi_t10dif, tlskeys, crypto_lookaside, ipsec_inline, rocev2, nic_hashfilter, nvme_tcp, ofld_sendpath
tp_l2t = 3072
tp_ddp = 2
tp_ddp_iscsi = 2
@@ -643,7 +646,7 @@
[fini]
version = 0x1425001d
- checksum = 0x96513217
+ checksum = 0x83f95163
# Total resources used by above allocations:
# Virtual Interfaces: 104
diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c
index 69ecfce1dade..d73204eb808c 100644
--- a/sys/dev/cxgbe/t4_main.c
+++ b/sys/dev/cxgbe/t4_main.c
@@ -3760,10 +3760,17 @@ port_mword(struct port_info *pi, uint32_t speed)
return (IFM_NONE);
}
break;
- case M_FW_PORT_CMD_PTYPE: /* FW_PORT_TYPE_NONE for old firmware */
- if (chip_id(pi->adapter) >= CHELSIO_T7)
- return (IFM_UNKNOWN);
- /* fall through */
+ case FW_PORT_TYPE_KR4_200G: {
+ /*
+ * Pre-T7 firmware used M_FW_PORT_CMD_PTYPE for PORT_TYPE_NONE
+ * and driver needs to deal with both.
+ */
+ _Static_assert(M_FW_PORT_CMD_PTYPE == FW_PORT_TYPE_KR4_200G,
+ "driver/firmware mismatch");
+ if (chip_id(pi->adapter) < CHELSIO_T7)
+ return (IFM_NONE);
+ return (IFM_200G_KR4_PAM4);
+ }
case FW_PORT_TYPE_NONE:
return (IFM_NONE);
}
diff --git a/sys/dev/eqos/if_eqos_starfive.c b/sys/dev/eqos/if_eqos_starfive.c
index 62f8b3f38983..f81118fd3094 100644
--- a/sys/dev/eqos/if_eqos_starfive.c
+++ b/sys/dev/eqos/if_eqos_starfive.c
@@ -17,6 +17,7 @@
#include <sys/socket.h>
#include <machine/bus.h>
+#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_media.h>
#include <dev/mii/mii.h>
@@ -40,6 +41,7 @@
#define JH7110_CSR_FREQ 198000000
#define WR4(sc, o, v) bus_write_4(sc->base.res[EQOS_RES_MEM], (o), (v))
+#define RD4(sc, o) bus_read_4(sc->base.res[EQOS_RES_MEM], (o))
static const struct ofw_compat_data compat_data[] = {
{"starfive,jh7110-dwmac", 1},
@@ -131,6 +133,8 @@ if_eqos_starfive_init(device_t dev)
struct if_eqos_starfive_softc *sc = device_get_softc(dev);
hwreset_t rst_ahb, rst_stmmaceth;
phandle_t node;
+ uint8_t eaddr[ETHER_ADDR_LEN];
+ uint32_t maclo, machi;
node = ofw_bus_get_node(dev);
@@ -186,6 +190,14 @@ if_eqos_starfive_init(device_t dev)
return (ENXIO);
}
+ if (OF_getprop(node, "local-mac-address", eaddr, sizeof(eaddr)) ==
+ sizeof(eaddr)) {
+ machi = eaddr[5] | (eaddr[4] << 8);
+ WR4(sc, GMAC_MAC_ADDRESS0_HIGH, machi);
+ maclo = eaddr[3] | (eaddr[2] << 8) | (eaddr[1] << 16) |
+ (eaddr[0] << 24);
+ WR4(sc, GMAC_MAC_ADDRESS0_LOW, maclo);
+ }
return (0);
}
diff --git a/sys/dev/mlx5/mlx5_en/mlx5_en_main.c b/sys/dev/mlx5/mlx5_en/mlx5_en_main.c
index 9bcb0dcf8e16..fb8b79c8f787 100644
--- a/sys/dev/mlx5/mlx5_en/mlx5_en_main.c
+++ b/sys/dev/mlx5/mlx5_en/mlx5_en_main.c
@@ -1135,25 +1135,6 @@ mlx5e_hw_clock(struct mlx5e_priv *priv)
}
/*
- * Seed the first calibration point so that base_prev and clbr_hw_prev
- * are always valid. Called once during attach before the first
- * calibration callout fires.
- */
-static void
-mlx5e_seed_calibration(struct mlx5e_priv *priv)
-{
- struct mlx5e_clbr_point *cp;
- struct timespec ts;
-
- cp = &priv->clbr_points[0];
- cp->clbr_hw_curr = mlx5e_hw_clock(priv);
- nanouptime(&ts);
- cp->base_curr = mlx5e_timespec2usec(&ts);
- cp->clbr_hw_prev = cp->clbr_hw_curr - 1;
- cp->base_prev = cp->base_curr - 1;
-}
-
-/*
* The calibration callout, it runs either in the context of the
* thread which enables calibration, or in callout. It takes the
* snapshot of system and adapter clocks, then advances the pointers to
@@ -1166,9 +1147,6 @@ mlx5e_calibration_callout(void *arg)
struct mlx5e_priv *priv;
struct mlx5e_clbr_point *next, *curr;
struct timespec ts;
- uint64_t hw_delta_new, hw_delta_old;
- uint64_t old_nsec, old_projected, old_sec;
- uint64_t res_n, res_s, res_s_mod, rt_delta_old;
int clbr_curr_next;
priv = arg;
@@ -1197,33 +1175,6 @@ mlx5e_calibration_callout(void *arg)
nanouptime(&ts);
next->base_curr = mlx5e_timespec2usec(&ts);
- /*
- * Ensure monotonicity across calibration transitions. Compute
- * what the old calibration would extrapolate to at the new
- * hw_curr. If the new base_curr is less, clamp it so the new
- * slope is at least as steep as the old one. This prevents
- * packets from seeing time go backwards when the slope drops.
- *
- * Use the same split-seconds technique as mlx5e_mbuf_tstmp()
- * to avoid overflowing uint64_t in the multiplication.
- */
- hw_delta_new = next->clbr_hw_curr - curr->clbr_hw_curr;
- rt_delta_old = curr->base_curr - curr->base_prev;
- hw_delta_old = curr->clbr_hw_curr - curr->clbr_hw_prev;
- old_sec = hw_delta_new / priv->cclk;
- old_nsec = hw_delta_new % priv->cclk;
- res_s = old_sec * rt_delta_old;
- res_n = old_nsec * rt_delta_old;
- res_s_mod = res_s % hw_delta_old;
- res_s /= hw_delta_old;
- res_s_mod *= priv->cclk;
- res_n += res_s_mod;
- res_n /= hw_delta_old;
- res_s *= priv->cclk;
- old_projected = curr->base_curr + res_s + res_n;
- if (next->base_curr < old_projected)
- next->base_curr = old_projected;
-
curr->clbr_gen = 0;
atomic_thread_fence_rel();
priv->clbr_curr = clbr_curr_next;
@@ -4936,7 +4887,6 @@ mlx5e_create_ifp(struct mlx5_core_dev *mdev)
callout_init(&priv->tstmp_clbr, 1);
/* Pull out the frequency of the clock in hz */
priv->cclk = (uint64_t)MLX5_CAP_GEN(mdev, device_frequency_khz) * 1000ULL;
- mlx5e_seed_calibration(priv);
mlx5e_reset_calibration_callout(priv);
pa.pa_version = PFIL_VERSION;
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index 0dddd2dd263f..b5a3012accd6 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -3756,7 +3756,7 @@ xhci_early_takeover(device_t self)
struct resource *res;
uint32_t cparams;
uint32_t eec;
- uint8_t eecp;
+ uint32_t eecp;
uint8_t bios_sem;
uint8_t offs;
int rid;
diff --git a/sys/dev/psci/psci.c b/sys/dev/psci/psci.c
index 2b250401ae83..872fae056a4b 100644
--- a/sys/dev/psci/psci.c
+++ b/sys/dev/psci/psci.c
@@ -133,7 +133,7 @@ static int psci_def_callfn(register_t, register_t, register_t, register_t,
psci_callfn_t psci_callfn = psci_def_callfn;
-static void
+void
psci_init(void *dummy)
{
psci_callfn_t new_callfn;
@@ -146,8 +146,11 @@ psci_init(void *dummy)
psci_callfn = new_callfn;
psci_present = true;
}
+
+#ifdef __arm__
/* This needs to be before cpu_mp at SI_SUB_CPU, SI_ORDER_THIRD */
SYSINIT(psci_start, SI_SUB_CPU, SI_ORDER_FIRST, psci_init, NULL);
+#endif
static int
psci_def_callfn(register_t a __unused, register_t b __unused,
@@ -631,3 +634,9 @@ psci_v0_2_init(device_t dev, int default_version)
device_printf(dev, "PSCI version number mismatched with DT\n");
return (1);
}
+
+bool
+psci_conduit_is_smc(void)
+{
+ return (psci_callfn == arm_smccc_smc);
+}
diff --git a/sys/dev/psci/psci.h b/sys/dev/psci/psci.h
index 6704eaf26c71..c250bf45d344 100644
--- a/sys/dev/psci/psci.h
+++ b/sys/dev/psci/psci.h
@@ -44,6 +44,9 @@ void psci_reset(void);
int32_t psci_features(uint32_t);
int psci_get_version(void);
+void psci_init(void *dummy);
+bool psci_conduit_is_smc(void);
+
/* Handler to let us call into the PSCI/SMCCC firmware */
extern psci_callfn_t psci_callfn;
static inline int
diff --git a/sys/dev/rge/if_rge.c b/sys/dev/rge/if_rge.c
index 8887e8d39ae4..06f034ebd61d 100644
--- a/sys/dev/rge/if_rge.c
+++ b/sys/dev/rge/if_rge.c
@@ -113,6 +113,7 @@ struct rge_matchid {
const struct rge_matchid rge_devices[] = {
{ PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_E3000, "Killer E3000" },
+ { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_E5000, "Killer E5000" },
{ PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RTL8125, "RTL8125" },
{ PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RTL8126, "RTL8126", },
{ PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RTL8127, "RTL8127" },
diff --git a/sys/dev/rge/if_rge_vendor.h b/sys/dev/rge/if_rge_vendor.h
index eea94e39e20b..f80b99f1f8b6 100644
--- a/sys/dev/rge/if_rge_vendor.h
+++ b/sys/dev/rge/if_rge_vendor.h
@@ -21,6 +21,7 @@
#define PCI_VENDOR_REALTEK 0x10ec
#define PCI_PRODUCT_REALTEK_E3000 0x3000
+#define PCI_PRODUCT_REALTEK_E5000 0x5000
#define PCI_PRODUCT_REALTEK_RTL8125 0x8125
#define PCI_PRODUCT_REALTEK_RTL8126 0x8126
#define PCI_PRODUCT_REALTEK_RTL8127 0x8127
diff --git a/sys/dev/syscons/syscons.c b/sys/dev/syscons/syscons.c
index 1a2969d6f2d8..fe440b68f209 100644
--- a/sys/dev/syscons/syscons.c
+++ b/sys/dev/syscons/syscons.c
@@ -3987,10 +3987,10 @@ next_code:
break;
case SUSP:
- power_pm_suspend(POWER_SSTATE_TRANSITION_SUSPEND);
+ power_pm_suspend(POWER_TRANSITION_SUSPEND);
break;
case STBY:
- power_pm_suspend(POWER_SSTATE_TRANSITION_STANDBY);
+ power_pm_suspend(POWER_TRANSITION_STANDBY);
break;
case DBG:
diff --git a/sys/dev/thunderbolt/tbcfg_reg.h b/sys/dev/thunderbolt/tbcfg_reg.h
index bb68faa543b0..6ae5c6fea7fa 100644
--- a/sys/dev/thunderbolt/tbcfg_reg.h
+++ b/sys/dev/thunderbolt/tbcfg_reg.h
@@ -52,7 +52,7 @@ struct tb_cfg_read {
uint32_t crc;
};
-/* Config space read request, 6.4.2.4 */
+/* Config space read response, 6.4.2.4 */
struct tb_cfg_read_resp {
tb_route_t route;
uint32_t addr_attrs;
diff --git a/sys/dev/ufshci/ufshci_private.h b/sys/dev/ufshci/ufshci_private.h
index 067b51a419e8..8d18fab982d7 100644
--- a/sys/dev/ufshci/ufshci_private.h
+++ b/sys/dev/ufshci/ufshci_private.h
@@ -262,11 +262,11 @@ static const struct ufshci_power_entry power_map[POWER_STYPE_COUNT] = {
UFSHCI_UIC_LINK_STATE_ACTIVE },
[POWER_STYPE_STANDBY] = { UFSHCI_DEV_PWR_SLEEP, SSS_PC_IDLE,
UFSHCI_UIC_LINK_STATE_HIBERNATE },
- [POWER_STYPE_SUSPEND_TO_MEM] = { UFSHCI_DEV_PWR_POWERDOWN,
+ [POWER_STYPE_FW_SUSPEND] = { UFSHCI_DEV_PWR_POWERDOWN,
SSS_PC_STANDBY, UFSHCI_UIC_LINK_STATE_HIBERNATE },
[POWER_STYPE_SUSPEND_TO_IDLE] = { UFSHCI_DEV_PWR_SLEEP, SSS_PC_IDLE,
UFSHCI_UIC_LINK_STATE_HIBERNATE },
- [POWER_STYPE_HIBERNATE] = { UFSHCI_DEV_PWR_DEEPSLEEP, 0x40,
+ [POWER_STYPE_FW_HIBERNATE] = { UFSHCI_DEV_PWR_DEEPSLEEP, 0x40,
UFSHCI_UIC_LINK_STATE_OFF },
[POWER_STYPE_POWEROFF] = { UFSHCI_DEV_PWR_POWERDOWN, SSS_PC_STANDBY,
UFSHCI_UIC_LINK_STATE_OFF },
diff --git a/sys/dev/vt/vt.h b/sys/dev/vt/vt.h
index 4abe99e4ab13..6ff242562c87 100644
--- a/sys/dev/vt/vt.h
+++ b/sys/dev/vt/vt.h
@@ -248,6 +248,8 @@ void vtbuf_cursor_visibility(struct vt_buf *, int);
int vtbuf_set_mark(struct vt_buf *vb, int type, int col, int row);
int vtbuf_get_marked_len(struct vt_buf *vb);
void vtbuf_extract_marked(struct vt_buf *vb, term_char_t *buf, int sz, int mark);
+void vtbuf_unmark(struct vt_buf *vb);
+void vtbuf_unmark_on_cross(struct vt_buf *vb, int target_begin, int target_end);
#endif
#define VTB_MARK_NONE 0
diff --git a/sys/dev/vt/vt_buf.c b/sys/dev/vt/vt_buf.c
index e1e4ebc23491..8596342c139a 100644
--- a/sys/dev/vt/vt_buf.c
+++ b/sys/dev/vt/vt_buf.c
@@ -202,6 +202,36 @@ vtbuf_in_this_range(int begin, int test, int end, int sz)
else
return (test >= begin && test < end);
}
+
+void
+vtbuf_unmark(struct vt_buf *vb)
+{
+
+ vtbuf_set_mark(vb, VTB_MARK_START, 0, 0);
+}
+
+void
+vtbuf_unmark_on_cross(struct vt_buf *vb, int target_begin, int target_end)
+{
+ int hsz, mb, me, tb, te;
+
+ tb = vtbuf_wth(vb, target_begin);
+ te = vtbuf_wth(vb, target_end);
+ mb = vb->vb_mark_start.tp_row;
+ me = vb->vb_mark_end.tp_row;
+ hsz = vb->vb_history_size;
+
+ /*
+ * Test intersection with vtbuf_in_this_range due to use of
+ * the circular buffer.
+ */
+ if (vtbuf_in_this_range(tb, mb, te, hsz) ||
+ vtbuf_in_this_range(tb, me, te, hsz) ||
+ vtbuf_in_this_range(mb, tb, me, hsz) ||
+ vtbuf_in_this_range(mb, te, me, hsz)) {
+ vtbuf_unmark(vb);
+ }
+}
#endif
int
diff --git a/sys/dev/vt/vt_core.c b/sys/dev/vt/vt_core.c
index f7cffcea5b92..641f6c014937 100644
--- a/sys/dev/vt/vt_core.c
+++ b/sys/dev/vt/vt_core.c
@@ -804,11 +804,11 @@ vt_machine_kbdevent(struct vt_device *vd, int c)
return (1);
case SPCLKEY | STBY: /* XXX Not present in kbdcontrol parser. */
/* Put machine into Stand-By mode. */
- power_pm_suspend(POWER_SSTATE_TRANSITION_STANDBY);
+ power_pm_suspend(POWER_TRANSITION_STANDBY);
return (1);
case SPCLKEY | SUSP: /* kbdmap(5) keyword `susp`. */
/* Suspend machine. */
- power_pm_suspend(POWER_SSTATE_TRANSITION_SUSPEND);
+ power_pm_suspend(POWER_TRANSITION_SUSPEND);
return (1);
}
@@ -1197,6 +1197,10 @@ vtterm_fill(struct terminal *tm, const term_rect_t *r, term_char_t c)
{
struct vt_window *vw = tm->tm_softc;
+#ifndef SC_NO_CUTPASTE
+ vtbuf_unmark_on_cross(&vw->vw_buf, r->tr_begin.tp_row,
+ r->tr_end.tp_row);
+#endif
vtbuf_fill(&vw->vw_buf, r, c);
}
@@ -2465,9 +2469,7 @@ vt_mouse_event(int type, int x, int y, int event, int cnt, int mlevel)
default:
vt_mouse_paste();
/* clear paste buffer selection after paste */
- vtbuf_set_mark(&vw->vw_buf, VTB_MARK_START,
- vd->vd_mx / vf->vf_width,
- vd->vd_my / vf->vf_height);
+ vtbuf_unmark(&vw->vw_buf);
break;
}
return; /* Done */
diff --git a/sys/dev/xen/control/control.c b/sys/dev/xen/control/control.c
index 2c61b48c0451..e363ea1700f6 100644
--- a/sys/dev/xen/control/control.c
+++ b/sys/dev/xen/control/control.c
@@ -176,12 +176,12 @@ xctrl_suspend(void)
cpuset_t cpu_suspend_map;
#endif
- EVENTHANDLER_INVOKE(power_suspend_early, POWER_STYPE_SUSPEND_TO_MEM);
+ EVENTHANDLER_INVOKE(power_suspend_early, POWER_STYPE_FW_SUSPEND);
xs_lock();
stop_all_proc();
xs_unlock();
suspend_all_fs();
- EVENTHANDLER_INVOKE(power_suspend, POWER_STYPE_SUSPEND_TO_MEM);
+ EVENTHANDLER_INVOKE(power_suspend, POWER_STYPE_FW_SUSPEND);
#ifdef EARLY_AP_STARTUP
MPASS(mp_ncpus == 1 || smp_started);
@@ -298,7 +298,7 @@ xctrl_suspend(void)
resume_all_fs();
resume_all_proc();
- EVENTHANDLER_INVOKE(power_resume, POWER_STYPE_SUSPEND_TO_MEM);
+ EVENTHANDLER_INVOKE(power_resume, POWER_STYPE_FW_SUSPEND);
if (bootverbose)
printf("System resumed after suspension\n");
diff --git a/sys/geom/part/g_part.c b/sys/geom/part/g_part.c
index 1e4236507fa4..6c4c37d9bfce 100644
--- a/sys/geom/part/g_part.c
+++ b/sys/geom/part/g_part.c
@@ -135,6 +135,7 @@ struct g_part_alias_list {
{ "vmware-vmfs", G_PART_ALIAS_VMFS },
{ "vmware-vmkdiag", G_PART_ALIAS_VMKDIAG },
{ "vmware-vsanhdr", G_PART_ALIAS_VMVSANHDR },
+ { "xbootldr", G_PART_ALIAS_XBOOTLDR },
};
SYSCTL_DECL(_kern_geom);
diff --git a/sys/geom/part/g_part.h b/sys/geom/part/g_part.h
index 575d97623e9b..1355cfec66a0 100644
--- a/sys/geom/part/g_part.h
+++ b/sys/geom/part/g_part.h
@@ -108,6 +108,8 @@ enum g_part_alias {
G_PART_ALIAS_VMKDIAG, /* A VMware vmkDiagnostic partition entry */
G_PART_ALIAS_VMRESERVED, /* A VMware reserved partition entry */
G_PART_ALIAS_VMVSANHDR, /* A VMware vSAN header partition entry */
+ G_PART_ALIAS_XBOOTLDR, /* A Systemd/Linux extended boot partition
+ Also used by visionfive2 as part of the boot sequence */
/* Keep the following last */
G_PART_ALIAS_COUNT
};
diff --git a/sys/geom/part/g_part_gpt.c b/sys/geom/part/g_part_gpt.c
index 4733631c4b20..eeca5fbfae17 100644
--- a/sys/geom/part/g_part_gpt.c
+++ b/sys/geom/part/g_part_gpt.c
@@ -230,6 +230,7 @@ static struct uuid gpt_uuid_vmfs = GPT_ENT_TYPE_VMFS;
static struct uuid gpt_uuid_vmkdiag = GPT_ENT_TYPE_VMKDIAG;
static struct uuid gpt_uuid_vmreserved = GPT_ENT_TYPE_VMRESERVED;
static struct uuid gpt_uuid_vmvsanhdr = GPT_ENT_TYPE_VMVSANHDR;
+static struct uuid gpt_uuid_xbootldr = GPT_ENT_TYPE_XBOOTLDR;
static struct g_part_uuid_alias {
struct uuid *uuid;
@@ -302,6 +303,7 @@ static struct g_part_uuid_alias {
{ &gpt_uuid_vmkdiag, G_PART_ALIAS_VMKDIAG, 0 },
{ &gpt_uuid_vmreserved, G_PART_ALIAS_VMRESERVED, 0 },
{ &gpt_uuid_vmvsanhdr, G_PART_ALIAS_VMVSANHDR, 0 },
+ { &gpt_uuid_xbootldr, G_PART_ALIAS_XBOOTLDR, 0 },
{ NULL, 0, 0 }
};
diff --git a/sys/i386/linux/linux_locore.asm b/sys/i386/linux/linux_locore.asm
index dbd0757c44bc..c188ad72f009 100644
--- a/sys/i386/linux/linux_locore.asm
+++ b/sys/i386/linux/linux_locore.asm
@@ -122,3 +122,5 @@ END(__kernel_vsyscall)
.balign 4
.previous
#endif
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/sys/kern/subr_physmem.c b/sys/kern/subr_physmem.c
index 6b97b36a6c51..7458c8147ad1 100644
--- a/sys/kern/subr_physmem.c
+++ b/sys/kern/subr_physmem.c
@@ -503,6 +503,12 @@ physmem_avail(vm_paddr_t *avail, size_t maxavail)
return (regions_to_avail(avail, EXFLAG_NOALLOC, maxavail, 0, NULL, NULL));
}
+size_t
+physmem_all(vm_paddr_t *avail, size_t maxavail)
+{
+ return (regions_to_avail(avail, 0, maxavail, 0, NULL, NULL));
+}
+
bool
physmem_excluded(vm_paddr_t pa, vm_size_t sz)
{
diff --git a/sys/kern/subr_power.c b/sys/kern/subr_power.c
index 13448cfa4d1e..47682a0ee75e 100644
--- a/sys/kern/subr_power.c
+++ b/sys/kern/subr_power.c
@@ -153,12 +153,12 @@ power_pm_register(u_int pm_type, power_pm_fn_t pm_fn, void *pm_arg,
sizeof(power_pm_supported));
if (power_pm_supported[POWER_STYPE_STANDBY])
power_standby_stype = POWER_STYPE_STANDBY;
- if (power_pm_supported[POWER_STYPE_SUSPEND_TO_MEM])
- power_suspend_stype = POWER_STYPE_SUSPEND_TO_MEM;
+ if (power_pm_supported[POWER_STYPE_FW_SUSPEND])
+ power_suspend_stype = POWER_STYPE_FW_SUSPEND;
else if (power_pm_supported[POWER_STYPE_SUSPEND_TO_IDLE])
power_suspend_stype = POWER_STYPE_SUSPEND_TO_IDLE;
- if (power_pm_supported[POWER_STYPE_HIBERNATE])
- power_hibernate_stype = POWER_STYPE_HIBERNATE;
+ if (power_pm_supported[POWER_STYPE_FW_HIBERNATE])
+ power_hibernate_stype = POWER_STYPE_FW_HIBERNATE;
error = 0;
TASK_INIT(&power_pm_task, 0, power_pm_deferred_fn, NULL);
} else {
@@ -176,7 +176,7 @@ power_pm_get_type(void)
}
void
-power_pm_suspend(enum power_sstate_transition trans)
+power_pm_suspend(enum power_transition trans)
{
enum power_stype stype;
@@ -184,13 +184,13 @@ power_pm_suspend(enum power_sstate_transition trans)
return;
switch (trans) {
- case POWER_SSTATE_TRANSITION_STANDBY:
+ case POWER_TRANSITION_STANDBY:
stype = power_standby_stype;
break;
- case POWER_SSTATE_TRANSITION_SUSPEND:
+ case POWER_TRANSITION_SUSPEND:
stype = power_suspend_stype;
break;
- case POWER_SSTATE_TRANSITION_HIBERNATE:
+ case POWER_TRANSITION_HIBERNATE:
stype = power_hibernate_stype;
break;
default:
diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
index 8ff9822ee9eb..2508f7edd1c5 100644
--- a/sys/kern/uipc_usrreq.c
+++ b/sys/kern/uipc_usrreq.c
@@ -83,6 +83,7 @@
#include <sys/socketvar.h>
#include <sys/signalvar.h>
#include <sys/stat.h>
+#include <sys/sysent.h>
#include <sys/sx.h>
#include <sys/sysctl.h>
#include <sys/systm.h>
@@ -2752,8 +2753,24 @@ uipc_ctloutput(struct socket *so, struct sockopt *sopt)
error = EINVAL;
}
UNP_PCB_UNLOCK(unp);
- if (error == 0)
- error = sooptcopyout(sopt, &xu, sizeof(xu));
+ if (error != 0)
+ break;
+#ifdef COMPAT_FREEBSD32
+ if (SV_PROC_FLAG(sopt->sopt_td->td_proc, SV_ILP32)) {
+ struct xucred32 xu32 = {};
+ int i;
+
+ xu32.cr_version = xu.cr_version;
+ xu32.cr_uid = xu.cr_uid;
+ xu32.cr_ngroups = xu.cr_ngroups;
+ for (i = 0; i < XU_NGROUPS; i++)
+ xu32.cr_groups[i] = xu.cr_groups[i];
+ xu32.cr_pid = xu.cr_pid;
+ error = sooptcopyout(sopt, &xu32, sizeof(xu32));
+ break;
+ }
+#endif
+ error = sooptcopyout(sopt, &xu, sizeof(xu));
break;
case LOCAL_CREDS:
diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c
index 3f8591bd0ba7..66210bf58a7c 100644
--- a/sys/kern/vfs_cache.c
+++ b/sys/kern/vfs_cache.c
@@ -5737,7 +5737,7 @@ cache_fplookup_climb_mount(struct cache_fpl *fpl)
prev_mp = NULL;
for (;;) {
- if (!vfs_op_thread_enter_crit(mp, mpcpu)) {
+ if (!vfs_op_thread_enter_crit(mp, &mpcpu)) {
if (prev_mp != NULL)
vfs_op_thread_exit_crit(prev_mp, prev_mpcpu);
return (cache_fpl_partial(fpl));
@@ -5792,7 +5792,7 @@ cache_fplookup_cross_mount(struct cache_fpl *fpl)
return (0);
}
- if (!vfs_op_thread_enter_crit(mp, mpcpu)) {
+ if (!vfs_op_thread_enter_crit(mp, &mpcpu)) {
return (cache_fpl_partial(fpl));
}
if (!vn_seqc_consistent(vp, vp_seqc)) {
diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c
index ddc5a1b70887..fff05a627162 100644
--- a/sys/kern/vfs_mount.c
+++ b/sys/kern/vfs_mount.c
@@ -500,7 +500,7 @@ vfs_ref_from_vp(struct vnode *vp)
if (__predict_false(mp == NULL)) {
return (mp);
}
- if (vfs_op_thread_enter(mp, mpcpu)) {
+ if (vfs_op_thread_enter(mp, &mpcpu)) {
if (__predict_true(mp == vp->v_mount)) {
vfs_mp_count_add_pcpu(mpcpu, ref, 1);
vfs_op_thread_exit(mp, mpcpu);
@@ -527,7 +527,7 @@ vfs_ref(struct mount *mp)
struct mount_pcpu *mpcpu;
CTR2(KTR_VFS, "%s: mp %p", __func__, mp);
- if (vfs_op_thread_enter(mp, mpcpu)) {
+ if (vfs_op_thread_enter(mp, &mpcpu)) {
vfs_mp_count_add_pcpu(mpcpu, ref, 1);
vfs_op_thread_exit(mp, mpcpu);
return;
@@ -645,7 +645,7 @@ vfs_rel(struct mount *mp)
struct mount_pcpu *mpcpu;
CTR2(KTR_VFS, "%s: mp %p", __func__, mp);
- if (vfs_op_thread_enter(mp, mpcpu)) {
+ if (vfs_op_thread_enter(mp, &mpcpu)) {
vfs_mp_count_sub_pcpu(mpcpu, ref, 1);
vfs_op_thread_exit(mp, mpcpu);
return;
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 823ccc6cab71..4bfbc0a7057e 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -237,15 +237,15 @@ static struct mtx mntid_mtx;
*/
static struct mtx __exclusive_cache_line vnode_list_mtx;
-static uma_zone_t buf_trie_zone;
-static smr_t buf_trie_smr;
+static __read_mostly uma_zone_t buf_trie_zone;
+static __read_mostly smr_t buf_trie_smr;
/* Zone for allocation of new vnodes - used exclusively by getnewvnode() */
-static uma_zone_t vnode_zone;
-MALLOC_DEFINE(M_VNODEPOLL, "VN POLL", "vnode poll");
-
+static __read_mostly uma_zone_t vnode_zone;
__read_frequently smr_t vfs_smr;
+MALLOC_DEFINE(M_VNODEPOLL, "VN POLL", "vnode poll");
+
/*
* The workitem queue.
*
@@ -876,7 +876,7 @@ vfs_busy(struct mount *mp, int flags)
MPASS((flags & ~MBF_MASK) == 0);
CTR3(KTR_VFS, "%s: mp %p with flags %d", __func__, mp, flags);
- if (vfs_op_thread_enter(mp, mpcpu)) {
+ if (vfs_op_thread_enter(mp, &mpcpu)) {
MPASS((mp->mnt_kern_flag & MNTK_DRAINING) == 0);
MPASS((mp->mnt_kern_flag & MNTK_UNMOUNT) == 0);
MPASS((mp->mnt_kern_flag & MNTK_REFEXPIRE) == 0);
@@ -939,7 +939,7 @@ vfs_unbusy(struct mount *mp)
CTR2(KTR_VFS, "%s: mp %p", __func__, mp);
- if (vfs_op_thread_enter(mp, mpcpu)) {
+ if (vfs_op_thread_enter(mp, &mpcpu)) {
MPASS((mp->mnt_kern_flag & MNTK_DRAINING) == 0);
vfs_mp_count_sub_pcpu(mpcpu, lockref, 1);
vfs_mp_count_sub_pcpu(mpcpu, ref, 1);
@@ -6090,7 +6090,7 @@ vop_create_post(void *ap, int rc)
a = ap;
dvp = a->a_dvp;
vn_seqc_write_end(dvp);
- if (!rc) {
+ if (rc == 0) {
VFS_KNOTE_LOCKED(dvp, NOTE_WRITE);
INOTIFY_NAME(*a->a_vpp, dvp, a->a_cnp, IN_CREATE);
}
@@ -6244,7 +6244,7 @@ vop_mknod_post(void *ap, int rc)
a = ap;
dvp = a->a_dvp;
vn_seqc_write_end(dvp);
- if (!rc) {
+ if (rc == 0) {
VFS_KNOTE_LOCKED(dvp, NOTE_WRITE);
INOTIFY_NAME(*a->a_vpp, dvp, a->a_cnp, IN_CREATE);
}
@@ -6512,8 +6512,10 @@ vop_read_pgcache_post(void *ap, int rc)
{
struct vop_read_pgcache_args *a = ap;
- if (!rc)
- VFS_KNOTE_UNLOCKED(a->a_vp, NOTE_READ);
+ if (rc == 0) {
+ VFS_KNOTE_LOCKED(a->a_vp, NOTE_READ);
+ INOTIFY(a->a_vp, IN_ACCESS);
+ }
}
static struct knlist fs_knlist;
@@ -6659,6 +6661,8 @@ vfs_knlunlock(void *arg)
{
struct vnode *vp = arg;
+ if (KNLIST_EMPTY(&vp->v_pollinfo->vpi_selinfo.si_note))
+ vn_irflag_unset(vp, VIRF_KNOTE);
VOP_UNLOCK(vp);
}
@@ -6706,7 +6710,11 @@ vfs_kqfilter(struct vop_kqfilter_args *ap)
return (ENOMEM);
knl = &vp->v_pollinfo->vpi_selinfo.si_note;
vhold(vp);
- knlist_add(knl, kn, 0);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+ knlist_add(knl, kn, 1);
+ if ((vn_irflag_read(vp) & VIRF_KNOTE) == 0)
+ vn_irflag_set(vp, VIRF_KNOTE);
+ VOP_UNLOCK(vp);
return (0);
}
@@ -6985,7 +6993,7 @@ vfs_cache_root(struct mount *mp, int flags, struct vnode **vpp)
struct vnode *vp;
int error;
- if (!vfs_op_thread_enter(mp, mpcpu))
+ if (!vfs_op_thread_enter(mp, &mpcpu))
return (vfs_cache_root_fallback(mp, flags, vpp));
vp = atomic_load_ptr(&mp->mnt_rootvnode);
if (vp == NULL || VN_IS_DOOMED(vp)) {
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index 4061b2272193..15704634ff62 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -2083,7 +2083,7 @@ vn_start_write_refed(struct mount *mp, int flags)
struct mount_pcpu *mpcpu;
int error, mflags;
- if ((flags & V_XSLEEP) == 0 && vfs_op_thread_enter(mp, mpcpu)) {
+ if ((flags & V_XSLEEP) == 0 && vfs_op_thread_enter(mp, &mpcpu)) {
MPASS((mp->mnt_kern_flag & MNTK_SUSPEND) == 0);
vfs_mp_count_add_pcpu(mpcpu, writeopcount, 1);
vfs_op_thread_exit(mp, mpcpu);
@@ -2252,7 +2252,7 @@ vn_finished_write(struct mount *mp)
if (mp == NULL)
return;
- if (vfs_op_thread_enter(mp, mpcpu)) {
+ if (vfs_op_thread_enter(mp, &mpcpu)) {
vfs_mp_count_sub_pcpu(mpcpu, writeopcount, 1);
vfs_mp_count_sub_pcpu(mpcpu, ref, 1);
vfs_op_thread_exit(mp, mpcpu);
diff --git a/sys/net/ieee8023ad_lacp.c b/sys/net/ieee8023ad_lacp.c
index 281d16bc6c05..8c695f71cc0f 100644
--- a/sys/net/ieee8023ad_lacp.c
+++ b/sys/net/ieee8023ad_lacp.c
@@ -682,6 +682,7 @@ static void
lacp_disable_distributing(struct lacp_port *lp)
{
struct lacp_aggregator *la = lp->lp_aggregator;
+ struct lacp_aggregator *la_active;
struct lacp_softc *lsc = lp->lp_lsc;
struct lagg_softc *sc = lsc->lsc_softc;
char buf[LACP_LAGIDSTR_MAX+1];
@@ -703,7 +704,6 @@ lacp_disable_distributing(struct lacp_port *lp)
TAILQ_REMOVE(&la->la_ports, lp, lp_dist_q);
la->la_nports--;
- sc->sc_active = la->la_nports;
if (lsc->lsc_active_aggregator == la) {
lacp_suppress_distributing(lsc, la);
@@ -713,6 +713,8 @@ lacp_disable_distributing(struct lacp_port *lp)
}
lp->lp_state &= ~LACP_STATE_DISTRIBUTING;
+ la_active = lsc->lsc_active_aggregator;
+ sc->sc_active = la_active != NULL ? la_active->la_nports : 0;
if_link_state_change(sc->sc_ifp,
sc->sc_active ? LINK_STATE_UP : LINK_STATE_DOWN);
}
@@ -721,6 +723,7 @@ static void
lacp_enable_distributing(struct lacp_port *lp)
{
struct lacp_aggregator *la = lp->lp_aggregator;
+ struct lacp_aggregator *la_active;
struct lacp_softc *lsc = lp->lp_lsc;
struct lagg_softc *sc = lsc->lsc_softc;
char buf[LACP_LAGIDSTR_MAX+1];
@@ -739,7 +742,6 @@ lacp_enable_distributing(struct lacp_port *lp)
KASSERT(la->la_refcnt > la->la_nports, ("aggregator refcnt invalid"));
TAILQ_INSERT_HEAD(&la->la_ports, lp, lp_dist_q);
la->la_nports++;
- sc->sc_active = la->la_nports;
lp->lp_state |= LACP_STATE_DISTRIBUTING;
@@ -750,6 +752,8 @@ lacp_enable_distributing(struct lacp_port *lp)
/* try to become the active aggregator */
lacp_select_active_aggregator(lsc);
+ la_active = lsc->lsc_active_aggregator;
+ sc->sc_active = la_active != NULL ? la_active->la_nports : 0;
if_link_state_change(sc->sc_ifp,
sc->sc_active ? LINK_STATE_UP : LINK_STATE_DOWN);
}
diff --git a/sys/net/if_geneve.c b/sys/net/if_geneve.c
index ab8b313e860a..59822045b77b 100644
--- a/sys/net/if_geneve.c
+++ b/sys/net/if_geneve.c
@@ -3021,6 +3021,7 @@ geneve_udp_input(struct mbuf *m, int offset, struct inpcb *inpcb,
if (sc == NULL)
return (false);
+ ifp = sc->gnv_ifp;
if ((sc->gnv_flags & GENEVE_FLAG_RUNNING) == 0)
goto out;
@@ -3043,7 +3044,6 @@ geneve_udp_input(struct mbuf *m, int offset, struct inpcb *inpcb,
if (error != 0)
goto out;
- ifp = sc->gnv_ifp;
if (ifp == m->m_pkthdr.rcvif)
/* XXX Does not catch more complex loops. */
goto out;
diff --git a/sys/net/if_media.h b/sys/net/if_media.h
index 892b7d1e3e52..5cc8714219c8 100644
--- a/sys/net/if_media.h
+++ b/sys/net/if_media.h
@@ -262,6 +262,8 @@ uint64_t ifmedia_baudrate(int);
#define IFM_1000_BX IFM_X(121) /* 1000Base-BX */
#define IFM_400G_SR8 IFM_X(122) /* 400GBase-SR8 */
#define IFM_400G_CR8 IFM_X(123) /* 400GBase-CR8 */
+#define IFM_10_T1S IFM_X(124) /* 10BASE-T1S */
+#define IFM_10_T1L IFM_X(125) /* 10BASE-T1L */
/*
* Please update ieee8023ad_lacp.c:lacp_compose_key()
@@ -554,6 +556,8 @@ struct ifmedia_description {
{ IFM_400G_AUI8, "400G-AUI8" }, \
{ IFM_400G_SR8, "400GBase-SR8" }, \
{ IFM_400G_CR8, "400GBase-CR8" }, \
+ { IFM_10_T1S, "10BASE-T1S" }, \
+ { IFM_10_T1L, "10BASE-T1L" }, \
{ 0, NULL }, \
}
@@ -903,6 +907,8 @@ struct ifmedia_baudrate {
{ IFM_ETHER | IFM_400G_AUI8, IF_Gbps(400ULL) }, \
{ IFM_ETHER | IFM_400G_SR8, IF_Gbps(400ULL) }, \
{ IFM_ETHER | IFM_400G_CR8, IF_Gbps(400ULL) }, \
+ { IFM_ETHER | IFM_10_T1S, IF_Mbps(10) }, \
+ { IFM_ETHER | IFM_10_T1L, IF_Mbps(10) }, \
\
{ IFM_IEEE80211 | IFM_IEEE80211_FH1, IF_Mbps(1) }, \
{ IFM_IEEE80211 | IFM_IEEE80211_FH2, IF_Mbps(2) }, \
diff --git a/sys/netpfil/ipfw/ip_fw2.c b/sys/netpfil/ipfw/ip_fw2.c
index 10690920e6fd..133aeeb969a6 100644
--- a/sys/netpfil/ipfw/ip_fw2.c
+++ b/sys/netpfil/ipfw/ip_fw2.c
@@ -780,7 +780,9 @@ static int
flow6id_match(int curr_flow, ipfw_insn_u32 *cmd)
{
int i;
- for (i=0; i <= cmd->o.arg1; ++i)
+ /* Mask proto version and traffic class out before comparing flow-id */
+ curr_flow &= ntohl(IPV6_FLOWLABEL_MASK);
+ for (i=0; i < cmd->o.arg1; ++i)
if (curr_flow == cmd->d[i])
return 1;
return 0;
diff --git a/sys/powerpc/include/_types.h b/sys/powerpc/include/_types.h
index 33cc6e731b50..746f9a4837c6 100644
--- a/sys/powerpc/include/_types.h
+++ b/sys/powerpc/include/_types.h
@@ -66,6 +66,7 @@ typedef __int32_t __register_t;
typedef __int32_t __segsz_t; /* segment size (in pages) */
#endif
typedef __int64_t __time_t; /* time()... */
+#define __SIZEOF_TIME_T __SIZEOF_INT64_T
typedef __uint32_t __uint_fast8_t;
typedef __uint32_t __uint_fast16_t;
typedef __uint32_t __uint_fast32_t;
diff --git a/sys/riscv/conf/GENERIC b/sys/riscv/conf/GENERIC
index 827d5efef50b..cce2787ed5d7 100644
--- a/sys/riscv/conf/GENERIC
+++ b/sys/riscv/conf/GENERIC
@@ -77,6 +77,7 @@ options RACCT # Resource accounting framework
options RACCT_DEFAULT_TO_DISABLED # Set kern.racct.enable=0 by default
options RCTL # Resource limits
options SMP
+options IOMMU
# RISC-V SBI console
device rcons
diff --git a/sys/riscv/include/_types.h b/sys/riscv/include/_types.h
index 3e9abd27a156..a9f95d4b6839 100644
--- a/sys/riscv/include/_types.h
+++ b/sys/riscv/include/_types.h
@@ -51,6 +51,7 @@ typedef __int64_t __int_fast64_t;
typedef __int64_t __register_t;
typedef __int64_t __segsz_t; /* segment size (in pages) */
typedef __int64_t __time_t; /* time()... */
+#define __SIZEOF_TIME_T __SIZEOF_INT64_T
typedef __uint32_t __uint_fast8_t;
typedef __uint32_t __uint_fast16_t;
typedef __uint32_t __uint_fast32_t;
diff --git a/sys/riscv/include/bus_dma_impl.h b/sys/riscv/include/bus_dma_impl.h
index 09fd29b74f8e..8c2040a68f52 100644
--- a/sys/riscv/include/bus_dma_impl.h
+++ b/sys/riscv/include/bus_dma_impl.h
@@ -41,6 +41,7 @@ struct bus_dma_tag_common {
int flags;
bus_dma_lock_t *lockfunc;
void *lockfuncarg;
+ int domain;
};
struct bus_dma_impl {
@@ -52,6 +53,8 @@ struct bus_dma_impl {
int (*tag_destroy)(bus_dma_tag_t dmat);
int (*map_create)(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp);
int (*map_destroy)(bus_dma_tag_t dmat, bus_dmamap_t map);
+ int (*tag_set_domain)(bus_dma_tag_t);
+ bool (*id_mapped)(bus_dma_tag_t, vm_paddr_t, bus_size_t);
int (*mem_alloc)(bus_dma_tag_t dmat, void** vaddr, int flags,
bus_dmamap_t *mapp);
void (*mem_free)(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map);
diff --git a/sys/riscv/include/iommu.h b/sys/riscv/include/iommu.h
new file mode 100644
index 000000000000..38214b7003f4
--- /dev/null
+++ b/sys/riscv/include/iommu.h
@@ -0,0 +1,10 @@
+/*-
+ * This file is in the public domain.
+ */
+
+#ifndef _MACHINE_IOMMU_H_
+#define _MACHINE_IOMMU_H_
+
+#include <riscv/iommu/iommu_frontend.h>
+
+#endif /* !_MACHINE_IOMMU_H_ */
diff --git a/sys/riscv/iommu/iommu.c b/sys/riscv/iommu/iommu.c
new file mode 100644
index 000000000000..59df2e68384f
--- /dev/null
+++ b/sys/riscv/iommu/iommu.c
@@ -0,0 +1,1351 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2026 Ruslan Bukin <br@bsdpad.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/bitstring.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/lock.h>
+#include <sys/sysctl.h>
+#include <sys/tree.h>
+#include <sys/taskqueue.h>
+#include <sys/refcount.h>
+#include <vm/vm.h>
+#include <vm/vm_page.h>
+
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/rman.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <dev/iommu/iommu.h>
+#include <riscv/iommu/iommu_pmap.h>
+#include <riscv/iommu/iommu.h>
+
+#include "iommu_if.h"
+
+#define dprintf(fmt, ...)
+
+MALLOC_DEFINE(M_IOMMU, "RISCV_IOMMU", "RISC-V IOMMU");
+
+#define RD4(sc, reg) bus_read_4(sc->res[0], (reg))
+#define WR4(sc, reg, val) bus_write_4(sc->res[0], (reg), (val))
+#define RD8(sc, reg) bus_read_8(sc->res[0], (reg))
+#define WR8(sc, reg, val) bus_write_8(sc->res[0], (reg), (val))
+
+#define CQ_ENTRY_DWORDS 2 /* 16-byte */
+#define CQ_ENTRY_COUNT 8192 /* Amount of 16-byte entries. */
+#define FQ_ENTRY_DWORDS 4 /* 32-byte */
+#define FQ_ENTRY_COUNT 8192 /* Amount of 32-byte entries. */
+#define PQ_ENTRY_DWORDS 2 /* 16-byte */
+#define PQ_ENTRY_COUNT 8192 /* Amount of 16-byte entries. */
+
+#define DDT_NON_LEAF_DWORDS 1
+#define DDT_DC_STD_DWORDS 4 /* Standard-format DC. */
+#define DDT_DC_EXT_DWORDS 8 /* Extended-format DC. */
+#define DDT_L1_DID_BITS 9 /* All formats. */
+
+#define QUEUE_ALIGN (1024 * 1024) /* TODO */
+#define QUEUE_HEAD(q) ((q)->csr + RISCV_IOMMU_CQH - RISCV_IOMMU_CQB)
+#define QUEUE_TAIL(q) ((q)->csr + RISCV_IOMMU_CQT - RISCV_IOMMU_CQB)
+#define QUEUE_IPSR(q) (1 << (q)->idx)
+
+#define PHYS_TO_PPN(p) ((p) >> 12)
+
+struct riscv_iommu_fq_event {
+ uint16_t cause_id;
+ char *descr;
+};
+
+static struct riscv_iommu_fq_event fq_events[] = {
+ { FQ_CAUSE_INST_FAULT, "Instruction access fault" },
+ { FQ_CAUSE_RD_ADDR_MISALIGNED, "Read address misaligned" },
+ { FQ_CAUSE_RD_FAULT, "Read access fault" },
+ { FQ_CAUSE_WR_ADDR_MISALIGNED, "Write/AMO address misaligned" },
+ { FQ_CAUSE_WR_FAULT, "Write/AMO access fault" },
+ { FQ_CAUSE_INST_FAULT_S, "Instruction page fault" },
+ { FQ_CAUSE_RD_FAULT_S, "Read page fault" },
+ { FQ_CAUSE_WR_FAULT_S, "Write/AMO page fault" },
+ { FQ_CAUSE_INST_FAULT_VS, "Instruction guest page fault" },
+ { FQ_CAUSE_RD_FAULT_VS, "Read guest-page fault" },
+ { FQ_CAUSE_WR_FAULT_VS, "Write/AMO guest-page fault" },
+ { FQ_CAUSE_DMA_DISABLED, "All inbound transactions disallowed" },
+ { FQ_CAUSE_DDT_LOAD_FAULT, "DDT entry load access fault" },
+ { FQ_CAUSE_DDT_INVALID, "DDT entry not valid" },
+ { FQ_CAUSE_DDT_MISCONFIGURED, "DDT entry misconfigured" },
+ { FQ_CAUSE_TR_TYPE_DISALLOWED, "Transaction type disallowed" },
+ { FQ_CAUSE_MSI_LOAD_FAULT, "MSI PTE load access fault" },
+ { FQ_CAUSE_MSI_INVALID, "MSI PTE not valid" },
+ { FQ_CAUSE_MSI_MISCONFIGURED, "MSI PTE misconfigured" },
+ { FQ_CAUSE_MRIF_FAULT, "MRIF access fault" },
+ { FQ_CAUSE_PDT_LOAD_FAULT, "PDT entry load access fault" },
+ { FQ_CAUSE_PDT_INVALID, "PDT entry not valid" },
+ { FQ_CAUSE_PDT_MISCONFIGURED, "PDT entry misconfigured" },
+ { FQ_CAUSE_DDT_CORRUPTED, "DDT data corruption" },
+ { FQ_CAUSE_PDT_CORRUPTED, "PDT data corruption" },
+ { FQ_CAUSE_MSI_PT_CORRUPTED, "MSI PT data corruption" },
+ { FQ_CAUSE_MRIF_CORRUPTED, "MSI MRIF data corruption" },
+ { FQ_CAUSE_INTERNAL_DP_ERROR, "Internal data path error" },
+ { FQ_CAUSE_MSI_WR_FAULT, "IOMMU MSI write access fault" },
+ { FQ_CAUSE_PT_CORRUPTED, "1st/2nd-stage PT data corruption" },
+ { 0, NULL },
+};
+
+static void
+riscv_iommu_init_pscids(struct riscv_iommu_softc *sc)
+{
+
+ sc->pscid_set_size = (1 << sc->pscid_bits);
+ sc->pscid_set = bit_alloc(sc->pscid_set_size, M_IOMMU, M_WAITOK);
+ mtx_init(&sc->pscid_set_mutex, "pscid set", NULL, MTX_SPIN);
+}
+
+static int
+riscv_iommu_pscid_alloc(struct riscv_iommu_softc *sc, int *new_pscid)
+{
+
+ mtx_lock_spin(&sc->pscid_set_mutex);
+ bit_ffc(sc->pscid_set, sc->pscid_set_size, new_pscid);
+ if (*new_pscid == -1) {
+ mtx_unlock_spin(&sc->pscid_set_mutex);
+ return (ENOMEM);
+ }
+ bit_set(sc->pscid_set, *new_pscid);
+ mtx_unlock_spin(&sc->pscid_set_mutex);
+
+ return (0);
+}
+
+static void
+riscv_iommu_pscid_free(struct riscv_iommu_softc *sc, int pscid)
+{
+
+ mtx_lock_spin(&sc->pscid_set_mutex);
+ bit_clear(sc->pscid_set, pscid);
+ mtx_unlock_spin(&sc->pscid_set_mutex);
+}
+
+static uint32_t
+riscv_iommu_q_inc_tail(struct riscv_iommu_queue *q)
+{
+
+ return ((q->lc.tail + 1) & q->mask);
+}
+
+static uint32_t
+riscv_iommu_q_inc_head(struct riscv_iommu_queue *q)
+{
+
+ return ((q->lc.head + 1) & q->mask);
+}
+
+static int
+riscv_iommu_q_has_space(struct riscv_iommu_queue *q)
+{
+
+ if (riscv_iommu_q_inc_tail(q) != q->lc.head)
+ return (1);
+
+ return (0);
+}
+
+static int
+riscv_iommu_q_empty(struct riscv_iommu_queue *q)
+{
+
+ if (q->lc.tail == q->lc.head)
+ return (1);
+
+ return (0);
+}
+
+static int
+riscv_iommu_dequeue(struct riscv_iommu_softc *sc, struct riscv_iommu_queue *q,
+ void *data)
+{
+ void *entry_addr;
+
+ q->lc.val = RD8(sc, q->head_off);
+ entry_addr = (void *)((uint64_t)q->vaddr + q->lc.head * q->entry_size);
+ memcpy(data, entry_addr, q->entry_size);
+ q->lc.head = riscv_iommu_q_inc_head(q);
+ WR4(sc, q->head_off, q->lc.head);
+
+ return (0);
+}
+
+static int
+riscv_iommu_enqueue(struct riscv_iommu_softc *sc, struct riscv_iommu_queue *q,
+ void *data)
+{
+ void *entry_addr;
+
+ RISCV_IOMMU_LOCK(sc);
+
+ /* Ensure that a space is available. */
+ do {
+ q->lc.head = RD4(sc, q->head_off);
+ } while (riscv_iommu_q_has_space(q) == 0);
+
+ /* Write the command to the current tail entry. */
+ entry_addr = (void *)((uint64_t)q->vaddr + q->lc.tail * q->entry_size);
+ memcpy(entry_addr, data, q->entry_size);
+
+ /* Increment tail index. */
+ q->lc.tail = riscv_iommu_q_inc_tail(q);
+ WR4(sc, q->tail_off, q->lc.tail);
+
+ RISCV_IOMMU_UNLOCK(sc);
+
+ return (0);
+}
+
+static void
+riscv_iommu_sync(struct riscv_iommu_softc *sc, struct riscv_iommu_queue *q)
+{
+ struct riscv_iommu_command cmd;
+ uint64_t reg;
+
+ bzero(&cmd, sizeof(struct riscv_iommu_command));
+ reg = COMMAND_OPCODE_IOFENCE;
+ reg |= FUNC_IOFENCE_FUNC_C | FUNC_IOFENCE_PR | FUNC_IOFENCE_PW;
+ cmd.dword0 = reg;
+
+ riscv_iommu_enqueue(sc, &sc->cq, (void *)&cmd);
+
+ /*
+ * FUNC_IOFENCE_WSI does not seem to be implemented in QEMU,
+ * so ensure all requests are processed in polling mode;
+ */
+ do {
+ q->lc.head = RD4(sc, q->head_off);
+ } while (riscv_iommu_q_empty(q) == 0);
+}
+
+static int
+riscv_iommu_inval_ddt(struct riscv_iommu_softc *sc)
+{
+ struct riscv_iommu_command cmd;
+ uint64_t reg;
+
+ bzero(&cmd, sizeof(struct riscv_iommu_command));
+ reg = COMMAND_OPCODE_IODIR;
+ reg |= FUNC_IODIR_INVAL_DDT;
+ cmd.dword0 = reg;
+
+ riscv_iommu_enqueue(sc, &sc->cq, (void *)&cmd);
+
+ return (0);
+}
+
+static int
+riscv_iommu_inval_ddt_did(struct riscv_iommu_softc *sc, int did)
+{
+ struct riscv_iommu_command cmd;
+ uint64_t reg;
+
+ bzero(&cmd, sizeof(struct riscv_iommu_command));
+ reg = COMMAND_OPCODE_IODIR;
+ reg |= FUNC_IODIR_INVAL_DDT;
+ reg |= FUNC_IODIR_DV;
+ reg |= (uint64_t)did << FUNC_IODIR_DID_S;
+ cmd.dword0 = reg;
+
+ riscv_iommu_enqueue(sc, &sc->cq, (void *)&cmd);
+
+ return (0);
+}
+
+/* Invalidate entire address space. */
+static int
+riscv_iommu_inval_vma(struct riscv_iommu_softc *sc)
+{
+ struct riscv_iommu_command cmd;
+ uint64_t reg;
+
+ bzero(&cmd, sizeof(struct riscv_iommu_command));
+ reg = COMMAND_OPCODE_IOTINVAL;
+ reg |= FUNC_IOTINVAL_VMA;
+ cmd.dword0 = reg;
+
+ riscv_iommu_enqueue(sc, &sc->cq, (void *)&cmd);
+
+ return (0);
+}
+
+static int
+riscv_iommu_inval_vma_page(struct riscv_iommu_softc *sc, vm_offset_t addr,
+ int pscid)
+{
+ struct riscv_iommu_command cmd;
+ uint64_t reg;
+
+ bzero(&cmd, sizeof(struct riscv_iommu_command));
+ reg = COMMAND_OPCODE_IOTINVAL;
+ reg |= FUNC_IOTINVAL_VMA;
+ reg |= FUNC_IOTINVAL_AV;
+ reg |= FUNC_IOTINVAL_PSCV;
+ reg |= pscid << FUNC_IOTINVAL_PSCID_S;
+ cmd.dword0 = reg;
+ cmd.dword1 = PHYS_TO_PPN(addr) << FUNC_IOTINVAL_ADDR_S;
+
+ riscv_iommu_enqueue(sc, &sc->cq, (void *)&cmd);
+
+ return (0);
+}
+
+static int
+riscv_iommu_inval_vma_pscid(struct riscv_iommu_softc *sc, int pscid)
+{
+ struct riscv_iommu_command cmd;
+ uint64_t reg;
+
+ bzero(&cmd, sizeof(struct riscv_iommu_command));
+ reg = COMMAND_OPCODE_IOTINVAL;
+ reg |= FUNC_IOTINVAL_VMA;
+ reg |= FUNC_IOTINVAL_PSCV;
+ reg |= pscid << FUNC_IOTINVAL_PSCID_S;
+ cmd.dword0 = reg;
+
+ riscv_iommu_enqueue(sc, &sc->cq, (void *)&cmd);
+
+ return (0);
+}
+
+static int
+riscv_iommu_set_mode(struct riscv_iommu_softc *sc)
+{
+ struct riscv_iommu_ddt *ddt;
+ uint64_t reg;
+ uint64_t base;
+
+ reg = RD8(sc, RISCV_IOMMU_DDTP);
+ if (reg & DDTP_BUSY)
+ return (ENXIO);
+
+ ddt = &sc->ddt;
+ base = ddt->base | (sc->iommu_mode << DDTP_IOMMU_MODE_S);
+ WR8(sc, RISCV_IOMMU_DDTP, base);
+
+ reg = RD8(sc, RISCV_IOMMU_DDTP);
+ if (reg != base) {
+ device_printf(sc->dev, "could not set mode\n");
+ return (ENXIO);
+ }
+
+ riscv_iommu_inval_ddt(sc);
+ riscv_iommu_inval_vma(sc);
+
+ return (0);
+}
+
+static int
+riscv_iommu_enable_queue(struct riscv_iommu_softc *sc,
+ struct riscv_iommu_queue *q)
+{
+ uint32_t reg;
+ int timeout;
+
+ if (q == &sc->cq)
+ WR4(sc, QUEUE_TAIL(q), 0);
+ else
+ WR4(sc, QUEUE_HEAD(q), 0);
+
+ reg = CQCSR_CQEN | CQCSR_CIE | CQCSR_CQMF;
+ WR4(sc, q->csr, reg);
+
+ timeout = 1000;
+ do {
+ reg = RD4(sc, RISCV_IOMMU_CQCSR);
+ if ((reg & CQCSR_BUSY) == 0)
+ break;
+ DELAY(10);
+ } while (timeout--);
+
+ if (timeout <= 0) {
+ device_printf(sc->dev, "could not enable command queue\n");
+ return (-1);
+ }
+
+ if ((reg & CQCSR_CQON) == 0) {
+ device_printf(sc->dev, "could not activate command queue\n");
+ return (-1);
+ }
+
+ /* RW1C interrupt pending bit. */
+ WR4(sc, RISCV_IOMMU_IPSR, QUEUE_IPSR(q));
+
+ return (0);
+}
+
+static int
+riscv_iommu_init_queue(struct riscv_iommu_softc *sc,
+ struct riscv_iommu_queue *q, uint64_t base, uint32_t dwords)
+{
+ uint64_t reg;
+ int sz;
+
+ q->entry_size = dwords * 8;
+ sz = (1 << q->size_log2) * q->entry_size;
+
+ /* Set up the command circular buffer */
+ q->vaddr = contigmalloc(sz, M_IOMMU, M_WAITOK | M_ZERO, 0,
+ (1ul << 48) - 1, QUEUE_ALIGN, 0);
+ if (q->vaddr == NULL) {
+ device_printf(sc->dev, "failed to allocate %d bytes\n", sz);
+ return (-1);
+ }
+
+ q->mask = (1 << q->size_log2) - 1;
+ q->head_off = (uint32_t)base - RISCV_IOMMU_CQB + RISCV_IOMMU_CQH;
+ q->tail_off = (uint32_t)base - RISCV_IOMMU_CQB + RISCV_IOMMU_CQT;
+ q->paddr = vtophys(q->vaddr);
+ q->base = (sc->cq.size_log2 - 1) << CQB_LOG2SZ_1_S;
+ q->base |= PHYS_TO_PPN(q->paddr) << CQB_PPN_S;
+ WR8(sc, base, q->base);
+
+ /* Verify it sticks. */
+ reg = RD8(sc, base);
+ if (reg != q->base) {
+ device_printf(sc->dev, "could not init queue\n");
+ return (ENXIO);
+ }
+
+ return (0);
+}
+
+static int
+riscv_iommu_init_queues(struct riscv_iommu_softc *sc)
+{
+ int error;
+
+ sc->cq.size_log2 = ilog2(CQ_ENTRY_COUNT);
+ sc->fq.size_log2 = ilog2(FQ_ENTRY_COUNT);
+ sc->pq.size_log2 = ilog2(PQ_ENTRY_COUNT);
+
+ sc->cq.csr = RISCV_IOMMU_CQCSR;
+ sc->fq.csr = RISCV_IOMMU_FQCSR;
+ sc->pq.csr = RISCV_IOMMU_PQCSR;
+
+ sc->cq.idx = 0;
+ sc->fq.idx = 1;
+ sc->pq.idx = 3;
+
+ /* Command queue (CQ). */
+ error = riscv_iommu_init_queue(sc, &sc->cq, RISCV_IOMMU_CQB,
+ CQ_ENTRY_DWORDS);
+ if (error)
+ return (error);
+
+ /* Fault queue (FQ). */
+ error = riscv_iommu_init_queue(sc, &sc->fq, RISCV_IOMMU_FQB,
+ FQ_ENTRY_DWORDS);
+ if (error)
+ return (error);
+
+ /* Page request queue (PQ). */
+ error = riscv_iommu_init_queue(sc, &sc->pq, RISCV_IOMMU_PQB,
+ PQ_ENTRY_DWORDS);
+ if (error)
+ return (error);
+
+ error = riscv_iommu_enable_queue(sc, &sc->cq);
+ if (error)
+ return (error);
+
+ error = riscv_iommu_enable_queue(sc, &sc->fq);
+ if (error)
+ return (error);
+
+ error = riscv_iommu_enable_queue(sc, &sc->pq);
+ if (error)
+ return (error);
+
+ return (0);
+}
+
+static int
+riscv_iommu_init_pagedir(struct riscv_iommu_softc *sc)
+{
+
+ return (0);
+}
+
+static void
+riscv_iommu_print_fault(struct riscv_iommu_softc *sc,
+ struct riscv_iommu_fq_record *rec)
+{
+ struct riscv_iommu_fq_event *ev;
+ uint16_t cause_id;
+ uint16_t ttyp;
+ uint32_t did;
+ uint32_t pid;
+ bool pv, priv;
+ int i;
+
+ cause_id = (rec->hdr & FQR_HDR_CAUSE_M) >> FQR_HDR_CAUSE_S;
+ ttyp = (rec->hdr & FQR_HDR_TTYP_M) >> FQR_HDR_TTYP_S;
+ did = (rec->hdr & FQR_HDR_DID_M) >> FQR_HDR_DID_S;
+ pid = (rec->hdr & FQR_HDR_PID_M) >> FQR_HDR_PID_S;
+ pv = (rec->hdr & FQR_HDR_PV) ? 1 : 0;
+ priv = (rec->hdr & FQR_HDR_PRIV) ? 1 : 0;
+
+ ev = NULL;
+ for (i = 0; fq_events[i].cause_id != 0; i++) {
+ if (fq_events[i].cause_id == cause_id) {
+ ev = &fq_events[i];
+ break;
+ }
+ }
+
+ if (ev == NULL) {
+ device_printf(sc->dev, "Fault: unknown fault 0x%x received\n",
+ cause_id);
+ return;
+ }
+
+ device_printf(sc->dev, "Fault: event 0x%x received: %s\n",
+ ev->cause_id, ev->descr);
+ device_printf(sc->dev, " hdr 0x%lx\n", rec->hdr);
+ device_printf(sc->dev, " iotval 0x%lx\n", rec->iotval);
+ device_printf(sc->dev, " iotval2 0x%lx\n", rec->iotval2);
+ device_printf(sc->dev, " ttyp 0x%x did 0x%x pid 0x%x pv %d priv %d"
+ "\n", ttyp, did, pid, pv, priv);
+}
+
+static int
+riscv_cq_intr(void *arg)
+{
+ struct riscv_iommu_softc *sc;
+ struct riscv_iommu_queue *q;
+ uint32_t reg;
+
+ sc = arg;
+ q = &sc->cq;
+
+ reg = RD4(sc, q->csr);
+ printf("%s: pending %x\n", __func__, reg);
+
+ /* Clear pending bit. */
+ WR4(sc, RISCV_IOMMU_IPSR, IPSR_CIP);
+
+ return (FILTER_HANDLED);
+}
+
+static int
+riscv_fq_intr(void *arg)
+{
+ struct riscv_iommu_fq_record rec;
+ struct riscv_iommu_softc *sc;
+ struct riscv_iommu_queue *q;
+ uint32_t reg;
+
+ sc = arg;
+ q = &sc->fq;
+
+ reg = RD4(sc, q->csr);
+ printf("%s: pending %x\n", __func__, reg);
+
+ /* Clear pending bit. */
+ WR4(sc, RISCV_IOMMU_IPSR, IPSR_FIP);
+
+ do {
+ riscv_iommu_dequeue(sc, q, &rec);
+ riscv_iommu_print_fault(sc, &rec);
+ } while (!riscv_iommu_q_empty(q));
+
+ return (FILTER_HANDLED);
+}
+
+static int
+riscv_pm_intr(void *arg)
+{
+ struct riscv_iommu_softc *sc;
+
+ sc = arg;
+
+ printf("%s\n", __func__);
+
+ /* Clear pending bit. */
+ WR4(sc, RISCV_IOMMU_IPSR, IPSR_PMIP);
+
+ return (FILTER_HANDLED);
+}
+
+static int
+riscv_pq_intr(void *arg)
+{
+ struct riscv_iommu_softc *sc;
+ struct riscv_iommu_queue *q;
+ uint32_t reg;
+
+ sc = arg;
+ q = &sc->pq;
+
+ reg = RD4(sc, q->csr);
+ printf("%s: pending %x\n", __func__, reg);
+
+ /* Clear pending bit. */
+ WR4(sc, RISCV_IOMMU_IPSR, IPSR_PIP);
+
+ return (FILTER_HANDLED);
+}
+
+static int
+riscv_iommu_init_ddt_linear(struct riscv_iommu_softc *sc)
+{
+ struct riscv_iommu_ddt *ddt;
+ uint64_t size;
+ uint64_t reg;
+
+ ddt = &sc->ddt;
+ ddt->num_top_entries = (1 << sc->l0_did_bits);
+
+ size = ddt->num_top_entries * (sc->dc_dwords << 3);
+
+ if (bootverbose)
+ device_printf(sc->dev, "linear ddt size %ld, num_top_entries "
+ "%d\n", size, ddt->num_top_entries);
+
+ ddt->vaddr = contigmalloc(size, M_IOMMU,
+ M_WAITOK | M_ZERO, /* flags */
+ 0, /* low */
+ (1ul << 48) - 1, /* high */
+ size, /* alignment */
+ 0); /* boundary */
+ if (ddt->vaddr == NULL) {
+ device_printf(sc->dev, "failed to allocate ddt\n");
+ return (ENXIO);
+ }
+
+ reg = vtophys(ddt->vaddr);
+ if (bootverbose)
+ device_printf(sc->dev, "ddt base %p size %lx\n", ddt->vaddr,
+ size);
+ ddt->base = PHYS_TO_PPN(reg) << DDTP_PPN_S;
+
+ return (0);
+}
+
+static int
+riscv_iommu_init_ddt_2lvl(struct riscv_iommu_softc *sc)
+{
+ struct riscv_iommu_ddt *ddt;
+ uint64_t size;
+ uint64_t reg;
+ uint64_t sz;
+
+ ddt = &sc->ddt;
+ ddt->num_top_entries = (1 << DDT_L1_DID_BITS);
+
+ size = ddt->num_top_entries * (DDT_NON_LEAF_DWORDS << 3);
+
+ if (bootverbose)
+ device_printf(sc->dev, "%s: size %lu, l1 entries %d, size "
+ "%lu\n", __func__, size, ddt->num_top_entries, size);
+
+ ddt->vaddr = contigmalloc(size, M_IOMMU,
+ M_WAITOK | M_ZERO, /* flags */
+ 0, /* low */
+ (1ul << 48) - 1, /* high */
+ size, /* alignment */
+ 0); /* boundary */
+ if (ddt->vaddr == NULL) {
+ device_printf(sc->dev, "Failed to allocate 2lvl ddt.\n");
+ return (ENOMEM);
+ }
+
+ sz = ddt->num_top_entries * sizeof(struct l1_desc);
+ ddt->l1 = malloc(sz, M_IOMMU, M_WAITOK | M_ZERO);
+
+ reg = vtophys(ddt->vaddr);
+ if (bootverbose)
+ device_printf(sc->dev, "ddt base %p size %lx\n", ddt->vaddr,
+ size);
+ ddt->base = PHYS_TO_PPN(reg) << DDTP_PPN_S;
+
+ return (0);
+}
+
+static int
+riscv_iommu_init_l0_directory(struct riscv_iommu_softc *sc, int sid)
+{
+ struct riscv_iommu_ddt *ddt;
+ struct l1_desc *l1_desc;
+ uint64_t *l1e;
+ uint64_t val;
+ size_t size;
+ int i;
+
+ ddt = &sc->ddt;
+ l1_desc = &ddt->l1[sid >> sc->l0_did_bits];
+ if (l1_desc->va) {
+ /* Already allocated. */
+ return (0);
+ }
+
+ size = (1 << sc->l0_did_bits) * (sc->dc_dwords << 3);
+
+ l1_desc->va = contigmalloc(size, M_IOMMU,
+ M_WAITOK | M_ZERO, /* flags */
+ 0, /* low */
+ (1ul << 48) - 1, /* high */
+ size, /* alignment */
+ 0); /* boundary */
+ if (l1_desc->va == NULL) {
+ device_printf(sc->dev, "failed to allocate l0 directory\n");
+ return (ENXIO);
+ }
+
+ l1_desc->pa = vtophys(l1_desc->va);
+
+ i = sid >> sc->l0_did_bits;
+ l1e = (void *)((uint64_t)ddt->vaddr + DDT_NON_LEAF_DWORDS * 8 * i);
+
+ /* Install the L1 entry. */
+ val = PHYS_TO_PPN(l1_desc->pa) << DC_NON_LEAF_ENTRY_PPN_S;
+ val |= DC_NON_LEAF_ENTRY_VALID;
+ *l1e = val;
+
+ return (0);
+}
+
+static void *
+riscv_iommu_get_dc_addr(struct riscv_iommu_softc *sc, int did)
+{
+ struct riscv_iommu_ddt *ddt;
+ struct l1_desc *l1_desc;
+ uintptr_t l0_base;
+ void *addr;
+ int l0_offs;
+ int l1_idx;
+
+ ddt = &sc->ddt;
+
+ l0_offs = sc->dc_dwords * 8 * (did & ((1 << sc->l0_did_bits) - 1));
+
+ if (sc->iommu_mode == DDTP_IOMMU_MODE_2LVL) {
+ l1_idx = (did >> sc->l0_did_bits) &
+ ((1 << DDT_L1_DID_BITS) - 1);
+ l1_desc = &ddt->l1[l1_idx];
+ l0_base = (uintptr_t)l1_desc->va;
+ } else
+ l0_base = (uintptr_t)ddt->vaddr;
+
+ addr = (void *)(l0_base + l0_offs);
+
+ dprintf("ddt vaddr %p addr %p\n", ddt->vaddr, addr);
+
+ return (addr);
+}
+
+static int
+riscv_iommu_init_dc(struct riscv_iommu_softc *sc,
+ struct riscv_iommu_domain *domain, int did, bool bypass)
+{
+ struct riscv_iommu_dc_base *dc_base;
+ struct riscv_iommu_dc *dc;
+ struct riscv_iommu_pmap *p;
+
+ dc = riscv_iommu_get_dc_addr(sc, did);
+ dc_base = &dc->base;
+
+ device_printf(sc->dev, "address translation for device id"
+ " 0x%x is %s.\n", did, bypass ? "bypassed" : "enabled");
+
+ p = &domain->p;
+
+ bzero(dc_base, sizeof(struct riscv_iommu_dc_base));
+ if (bypass == false)
+ dc_base->fsc = p->pm_satp;
+ dc_base->ta = (domain->pscid << DC_TA_PSCID_S) | DC_TA_V;
+
+ riscv_iommu_inval_ddt_did(sc, did);
+ riscv_iommu_sync(sc, &sc->cq);
+ dc_base->tc |= DC_TC_V;
+ riscv_iommu_inval_ddt_did(sc, did);
+ riscv_iommu_inval_vma(sc);
+ riscv_iommu_sync(sc, &sc->cq);
+
+ return (0);
+}
+
+static void
+riscv_iommu_deinit_dc(struct riscv_iommu_softc *sc, int did)
+{
+ struct riscv_iommu_dc_base *dc_base;
+ struct riscv_iommu_dc *dc;
+
+ dc = riscv_iommu_get_dc_addr(sc, did);
+ dc_base = &dc->base;
+ dc_base->tc &= ~DC_TC_V;
+
+ riscv_iommu_inval_ddt_did(sc, did);
+ riscv_iommu_sync(sc, &sc->cq);
+}
+
+static int
+riscv_iommu_setup_interrupts(struct riscv_iommu_softc *sc)
+{
+ device_t dev;
+ int error;
+
+ dev = sc->dev;
+
+ if (sc->res[1] == NULL || sc->res[2] == NULL ||
+ sc->res[3] == NULL || sc->res[4] == NULL) {
+ device_printf(dev, "Warning: no interrupt resources "
+ "provided.\n");
+ return (ENXIO);
+ }
+
+ error = bus_setup_intr(dev, sc->res[1], INTR_TYPE_MISC,
+ riscv_cq_intr, NULL, sc, &sc->intr_cookie[0]);
+ if (error) {
+ device_printf(dev, "Couldn't setup cq interrupt handler\n");
+ return (ENXIO);
+ }
+
+ error = bus_setup_intr(dev, sc->res[2], INTR_TYPE_MISC,
+ riscv_fq_intr, NULL, sc, &sc->intr_cookie[1]);
+ if (error) {
+ device_printf(dev, "Couldn't setup fq interrupt handler\n");
+ return (ENXIO);
+ }
+
+ error = bus_setup_intr(dev, sc->res[3], INTR_TYPE_MISC,
+ riscv_pm_intr, NULL, sc, &sc->intr_cookie[2]);
+ if (error) {
+ device_printf(dev, "Couldn't setup pm interrupt handler\n");
+ return (ENXIO);
+ }
+
+ error = bus_setup_intr(dev, sc->res[4], INTR_TYPE_MISC,
+ riscv_pq_intr, NULL, sc, &sc->intr_cookie[3]);
+ if (error) {
+ device_printf(dev, "Couldn't setup pq interrupt handler\n");
+ return (ENXIO);
+ }
+
+ WR8(sc, RISCV_IOMMU_ICVEC, 0 << 0 | 1 << 4 | 2 << 8 | 3 << 12);
+
+ return (0);
+}
+
+int
+riscv_iommu_attach(device_t dev)
+{
+ struct riscv_iommu_softc *sc;
+ uint64_t caps;
+ int error;
+
+ sc = device_get_softc(dev);
+
+ caps = bus_read_8(sc->res[0], RISCV_IOMMU_CAPABILITIES);
+ if (bootverbose)
+ device_printf(sc->dev, "IOMMU Capabilities: %lx\n", caps);
+
+ device_printf(sc->dev, "Device-Context structure is %s.\n",
+ caps & CAPABILITIES_MSI_FLAT ?
+ "64-bytes (ext format)" : "32-bytes (std format)");
+
+ if (caps & CAPABILITIES_MSI_FLAT) {
+ sc->dc_dwords = DDT_DC_EXT_DWORDS;
+ sc->l0_did_bits = 6;
+ } else {
+ sc->dc_dwords = DDT_DC_STD_DWORDS;
+ sc->l0_did_bits = 7;
+ }
+
+ if (caps & CAPABILITIES_SV48)
+ sc->pm_mode = PMAP_MODE_SV48;
+ else if (caps & CAPABILITIES_SV39)
+ sc->pm_mode = PMAP_MODE_SV39;
+ else {
+ device_printf(sc->dev, "Unsupported virtual memory system\n");
+ return (ENXIO);
+ }
+
+ mtx_init(&sc->mtx, device_get_nameunit(sc->dev), "riscv_iommu",
+ MTX_DEF);
+
+ WR4(sc, RISCV_IOMMU_FCTL, FCTL_WSI);
+
+ error = riscv_iommu_setup_interrupts(sc);
+ if (error) {
+ device_printf(sc->dev, "Could not setup interrupts. "
+ "Continuing with no interrupts support.");
+ }
+
+ error = riscv_iommu_init_pagedir(sc);
+ if (error)
+ return (error);
+
+ error = riscv_iommu_init_queues(sc);
+ if (error)
+ return (error);
+
+ sc->iommu_mode = DDTP_IOMMU_MODE_2LVL;
+
+ switch (sc->iommu_mode) {
+ case DDTP_IOMMU_MODE_1LVL:
+ error = riscv_iommu_init_ddt_linear(sc);
+ break;
+ case DDTP_IOMMU_MODE_2LVL:
+ error = riscv_iommu_init_ddt_2lvl(sc);
+ break;
+ default:
+ error = ENXIO;
+ }
+ if (error)
+ return (error);
+
+ sc->pscid_bits = 8;
+
+ riscv_iommu_init_pscids(sc);
+ if (error)
+ return (error);
+
+ error = riscv_iommu_set_mode(sc);
+ if (error)
+ return (error);
+
+ return (0);
+}
+
+static int
+riscv_iommu_set_buswide(device_t dev, struct riscv_iommu_domain *domain,
+ struct riscv_iommu_ctx *ctx)
+{
+ struct riscv_iommu_softc *sc;
+ int i;
+
+ sc = device_get_softc(dev);
+
+ printf("%s\n", __func__);
+
+ for (i = 0; i < PCI_SLOTMAX; i++)
+ riscv_iommu_init_dc(sc, domain, (ctx->did | i),
+ ctx->bypass);
+
+ return (0);
+}
+
+static int
+riscv_iommu_pci_get_did(device_t child, uintptr_t *xref0, u_int *did0)
+{
+ struct pci_id_ofw_iommu pi;
+ int err;
+
+ dprintf("%s\n", __func__);
+
+ err = pci_get_id(child, PCI_ID_OFW_IOMMU, (uintptr_t *)&pi);
+ if (err == 0) {
+ if (did0)
+ *did0 = pi.id;
+ if (xref0)
+ *xref0 = pi.xref;
+ }
+
+ return (err);
+}
+
+static int
+riscv_iommu_find(device_t dev, device_t child)
+{
+ struct riscv_iommu_softc *sc;
+ uintptr_t xref;
+ int err;
+
+ dprintf("%s\n", __func__);
+
+ sc = device_get_softc(dev);
+
+ err = riscv_iommu_pci_get_did(child, &xref, NULL);
+ if (err)
+ return (ENOENT);
+
+ /* Check if xref is ours. */
+ dprintf("xref %lx sc->xref %lx\n", xref, sc->xref);
+ if (xref != sc->xref)
+ return (EFAULT);
+
+ return (0);
+}
+
+struct riscv_iommu_ctx *
+riscv_iommu_ctx_lookup_by_did(device_t dev, u_int did)
+{
+ struct riscv_iommu_softc *sc;
+ struct riscv_iommu_domain *domain;
+ struct riscv_iommu_unit *unit;
+ struct riscv_iommu_ctx *ctx;
+
+ dprintf("%s\n", __func__);
+ sc = device_get_softc(dev);
+
+ unit = &sc->unit;
+
+ LIST_FOREACH(domain, &unit->domain_list, next) {
+ LIST_FOREACH(ctx, &domain->ctx_list, next) {
+ if (ctx->did == did) {
+ refcount_acquire(&ctx->refcnt);
+ return (ctx);
+ }
+ }
+ }
+
+ return (NULL);
+}
+
+static struct iommu_ctx *
+riscv_iommu_ctx_lookup(device_t dev, device_t child)
+{
+ struct iommu_unit *iommu __diagused;
+ struct riscv_iommu_softc *sc;
+ struct riscv_iommu_domain *domain;
+ struct riscv_iommu_unit *unit;
+ struct riscv_iommu_ctx *ctx;
+
+ dprintf("%s\n", __func__);
+ sc = device_get_softc(dev);
+
+ unit = &sc->unit;
+ iommu = &unit->iommu;
+
+ IOMMU_ASSERT_LOCKED(iommu);
+
+ LIST_FOREACH(domain, &unit->domain_list, next) {
+ IOMMU_DOMAIN_LOCK(&domain->iodom);
+ LIST_FOREACH(ctx, &domain->ctx_list, next) {
+ if (ctx->dev == child) {
+ refcount_acquire(&ctx->refcnt);
+ IOMMU_DOMAIN_UNLOCK(&domain->iodom);
+ return (&ctx->ioctx);
+ }
+ }
+ IOMMU_DOMAIN_UNLOCK(&domain->iodom);
+ }
+
+ return (NULL);
+}
+
+static int
+riscv_iommu_unmap(device_t dev, struct iommu_domain *iodom,
+ vm_offset_t va, bus_size_t size)
+{
+ struct riscv_iommu_domain *domain;
+ struct riscv_iommu_softc *sc;
+ int err;
+ int i;
+
+ sc = device_get_softc(dev);
+
+ domain = (struct riscv_iommu_domain *)iodom;
+
+ err = 0;
+
+ dprintf("%s: %lx, %ld, domain %d\n", __func__, va, size, domain->pscid);
+
+ for (i = 0; i < size; i += PAGE_SIZE) {
+ if (iommu_pmap_remove(&domain->p, va) == 0) {
+ /* pmap entry removed, invalidate TLB. */
+ riscv_iommu_inval_vma_page(sc, va, domain->pscid);
+ } else {
+ err = ENOENT;
+ break;
+ }
+ va += PAGE_SIZE;
+ }
+
+ riscv_iommu_sync(sc, &sc->cq);
+
+ return (err);
+}
+
+static int
+riscv_iommu_map(device_t dev, struct iommu_domain *iodom,
+ vm_offset_t va, vm_page_t *ma, vm_size_t size,
+ vm_prot_t prot)
+{
+ struct riscv_iommu_domain *domain;
+ struct riscv_iommu_softc *sc;
+ vm_paddr_t pa;
+ int error;
+ int i;
+
+ sc = device_get_softc(dev);
+
+ domain = (struct riscv_iommu_domain *)iodom;
+
+ for (i = 0; size > 0; size -= PAGE_SIZE) {
+ pa = VM_PAGE_TO_PHYS(ma[i++]);
+ dprintf("%s: %lx -> %lx, %ld, domain %d\n", __func__, va, pa,
+ size, domain->pscid);
+ error = iommu_pmap_enter(&domain->p, va, pa, prot, 0);
+ if (error)
+ return (error);
+ riscv_iommu_inval_vma_page(sc, va, domain->pscid);
+ va += PAGE_SIZE;
+ }
+
+ riscv_iommu_sync(sc, &sc->cq);
+
+ return (0);
+}
+
+static struct iommu_domain *
+riscv_iommu_domain_alloc(device_t dev, struct iommu_unit *iommu)
+{
+ struct iommu_domain *iodom;
+ struct riscv_iommu_domain *domain;
+ struct riscv_iommu_unit *unit;
+ struct riscv_iommu_softc *sc;
+ int new_pscid;
+ int va_bits;
+ int error;
+
+ sc = device_get_softc(dev);
+
+ dprintf("%s\n", __func__);
+
+ unit = (struct riscv_iommu_unit *)iommu;
+
+ error = riscv_iommu_pscid_alloc(sc, &new_pscid);
+ if (error) {
+ device_printf(sc->dev,
+ "Could not allocate PSCID for a new domain.\n");
+ return (NULL);
+ }
+
+ domain = malloc(sizeof(*domain), M_IOMMU, M_WAITOK | M_ZERO);
+ domain->pscid = (uint16_t)new_pscid;
+
+ iommu_pmap_pinit(&domain->p, sc->pm_mode);
+
+ riscv_iommu_inval_vma_pscid(sc, domain->pscid);
+
+ LIST_INIT(&domain->ctx_list);
+
+ IOMMU_LOCK(iommu);
+ LIST_INSERT_HEAD(&unit->domain_list, domain, next);
+ IOMMU_UNLOCK(iommu);
+
+ iodom = &domain->iodom;
+
+ va_bits = sc->pm_mode == PMAP_MODE_SV48 ? 48 : 39;
+
+ /* Avoid sign-extension. */
+ va_bits -= 1;
+
+ iodom->end = (1ULL << va_bits) - 1;
+
+ return (iodom);
+}
+
+static void
+riscv_iommu_domain_free(device_t dev, struct iommu_domain *iodom)
+{
+ struct riscv_iommu_domain *domain;
+ struct riscv_iommu_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ dprintf("%s\n", __func__);
+
+ domain = (struct riscv_iommu_domain *)iodom;
+
+ LIST_REMOVE(domain, next);
+
+ iommu_pmap_remove_pages(&domain->p);
+ iommu_pmap_release(&domain->p);
+
+ riscv_iommu_inval_vma_pscid(sc, domain->pscid);
+ riscv_iommu_pscid_free(sc, domain->pscid);
+
+ free(domain, M_IOMMU);
+}
+
+static struct iommu_ctx *
+riscv_iommu_ctx_alloc(device_t dev, struct iommu_domain *iodom, device_t child,
+ bool disabled)
+{
+ struct riscv_iommu_domain *domain;
+ struct riscv_iommu_ctx *ctx;
+
+ dprintf("%s\n", __func__);
+
+ domain = (struct riscv_iommu_domain *)iodom;
+
+ ctx = malloc(sizeof(struct riscv_iommu_ctx), M_IOMMU,
+ M_WAITOK | M_ZERO);
+ ctx->dev = child;
+ ctx->domain = domain;
+ refcount_init(&ctx->refcnt, 1);
+ if (disabled)
+ ctx->bypass = true;
+
+ IOMMU_DOMAIN_LOCK(iodom);
+ LIST_INSERT_HEAD(&domain->ctx_list, ctx, next);
+ IOMMU_DOMAIN_UNLOCK(iodom);
+
+ return (&ctx->ioctx);
+}
+
+static int
+riscv_iommu_ctx_init(device_t dev, struct iommu_ctx *ioctx)
+{
+ struct riscv_iommu_domain *domain;
+ struct iommu_domain *iodom;
+ struct riscv_iommu_softc *sc;
+ struct riscv_iommu_ctx *ctx;
+ devclass_t pci_class;
+ u_int did;
+ int error;
+
+ ctx = (struct riscv_iommu_ctx *)ioctx;
+
+ dprintf("%s\n", __func__);
+
+ sc = device_get_softc(dev);
+
+ domain = ctx->domain;
+ iodom = (struct iommu_domain *)domain;
+
+ pci_class = devclass_find("pci");
+ if (device_get_devclass(device_get_parent(ctx->dev)) == pci_class) {
+ error = riscv_iommu_pci_get_did(ctx->dev, NULL, &did);
+ if (error)
+ return (error);
+
+ ioctx->rid = pci_get_rid(dev);
+ ctx->did = did;
+ ctx->vendor = pci_get_vendor(ctx->dev);
+ ctx->device = pci_get_device(ctx->dev);
+ }
+
+ if (sc->iommu_mode == DDTP_IOMMU_MODE_2LVL) {
+ error = riscv_iommu_init_l0_directory(sc, ctx->did);
+ if (error)
+ return (error);
+ }
+ riscv_iommu_init_dc(sc, domain, ctx->did, ctx->bypass);
+
+ if (device_get_devclass(device_get_parent(ctx->dev)) == pci_class)
+ if (iommu_is_buswide_ctx(iodom->iommu, pci_get_bus(ctx->dev)))
+ riscv_iommu_set_buswide(dev, domain, ctx);
+
+ return (0);
+}
+
+static bool
+riscv_iommu_ctx_free(device_t dev, struct iommu_ctx *ioctx)
+{
+ struct riscv_iommu_softc *sc;
+ struct riscv_iommu_ctx *ctx;
+
+ dprintf("%s\n", __func__);
+
+ IOMMU_ASSERT_LOCKED(ioctx->domain->iommu);
+
+ sc = device_get_softc(dev);
+
+ ctx = (struct riscv_iommu_ctx *)ioctx;
+ if (refcount_release(&ctx->refcnt)) {
+ riscv_iommu_deinit_dc(sc, ctx->did);
+ LIST_REMOVE(ctx, next);
+ free(ctx, M_IOMMU);
+ return (true);
+ }
+
+ return (false);
+}
+
+#ifdef FDT
+static int
+riscv_iommu_ofw_md_data(device_t dev, struct iommu_ctx *ioctx, pcell_t *cells,
+ int ncells)
+{
+ struct riscv_iommu_ctx *ctx;
+
+ printf("%s\n", __func__);
+ ctx = (struct riscv_iommu_ctx *)ioctx;
+
+ if (ncells != 1)
+ return (-1);
+
+ ctx->did = cells[0];
+
+ return (0);
+}
+#endif
+
+static int
+riscv_iommu_read_ivar(device_t dev, device_t child, int which,
+ uintptr_t *result)
+{
+ struct riscv_iommu_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ device_printf(sc->dev, "%s\n", __func__);
+
+ return (ENOENT);
+}
+
+static device_method_t riscv_iommu_methods[] = {
+ /* IOMMU interface */
+ DEVMETHOD(iommu_find, riscv_iommu_find),
+ DEVMETHOD(iommu_map, riscv_iommu_map),
+ DEVMETHOD(iommu_unmap, riscv_iommu_unmap),
+ DEVMETHOD(iommu_domain_alloc, riscv_iommu_domain_alloc),
+ DEVMETHOD(iommu_domain_free, riscv_iommu_domain_free),
+ DEVMETHOD(iommu_ctx_alloc, riscv_iommu_ctx_alloc),
+ DEVMETHOD(iommu_ctx_init, riscv_iommu_ctx_init),
+ DEVMETHOD(iommu_ctx_free, riscv_iommu_ctx_free),
+ DEVMETHOD(iommu_ctx_lookup, riscv_iommu_ctx_lookup),
+#ifdef FDT
+ DEVMETHOD(iommu_ofw_md_data, riscv_iommu_ofw_md_data),
+#endif
+
+ /* Bus interface */
+ DEVMETHOD(bus_read_ivar, riscv_iommu_read_ivar),
+
+ /* End */
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_0(riscv_iommu, riscv_iommu_driver, riscv_iommu_methods,
+ sizeof(struct riscv_iommu_softc));
diff --git a/sys/riscv/iommu/iommu.h b/sys/riscv/iommu/iommu.h
new file mode 100644
index 000000000000..502a0e121bd1
--- /dev/null
+++ b/sys/riscv/iommu/iommu.h
@@ -0,0 +1,359 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2026 Ruslan Bukin <br@bsdpad.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _RISCV_IOMMU_IOMMU_H_
+#define _RISCV_IOMMU_IOMMU_H_
+
+#define RISCV_IOMMU_CAPABILITIES 0x0000
+#define CAPABILITIES_VERSION_S 0
+#define CAPABILITIES_VERSION_M (0xff << CAPABILITIES_VERSION_S)
+#define CAPABILITIES_SV32 (1 << 8)
+#define CAPABILITIES_SV39 (1 << 9)
+#define CAPABILITIES_SV48 (1 << 10)
+#define CAPABILITIES_SV57 (1 << 11)
+#define CAPABILITIES_SVPBMT (1 << 15)
+#define CAPABILITIES_SV32X4 (1 << 16)
+#define CAPABILITIES_SV39X4 (1 << 17)
+#define CAPABILITIES_SV48X4 (1 << 18)
+#define CAPABILITIES_SV57X4 (1 << 19)
+#define CAPABILITIES_AMO_MRIF (1 << 21)
+#define CAPABILITIES_MSI_FLAT (1 << 22)
+#define CAPABILITIES_MSI_MRIF (1 << 23)
+#define CAPABILITIES_AMO_HWAD (1 << 24)
+#define CAPABILITIES_ATS (1 << 25)
+#define CAPABILITIES_T2GPA (1 << 26)
+#define CAPABILITIES_END (1 << 27)
+#define CAPABILITIES_IGS_S 28
+#define CAPABILITIES_IGS_M (0x3 << CAPABILITIES_IGS_S)
+#define CAPABILITIES_HPM (1 << 30)
+#define CAPABILITIES_DBG (1 << 31)
+#define CAPABILITIES_PAS_S 32ULL
+#define CAPABILITIES_PAS_M (0x3f << CAPABILITIES_PAS_S)
+#define CAPABILITIES_PD8 (1ULL << 38)
+#define CAPABILITIES_PD17 (1ULL << 39)
+#define CAPABILITIES_PD20 (1ULL << 40)
+#define RISCV_IOMMU_FCTL 0x0008
+#define FCTL_BE (1 << 0) /* Big-endian */
+#define FCTL_WSI (1 << 1) /* Wire-signalled Ints. */
+#define FCTL_GXL (1 << 2) /* Guest physical addresses */
+#define RISCV_IOMMU_DDTP 0x0010
+#define DDTP_IOMMU_MODE_S 0
+#define DDTP_IOMMU_MODE_OFF (0 << DDTP_IOMMU_MODE_S)
+#define DDTP_IOMMU_MODE_BARE (1 << DDTP_IOMMU_MODE_S)
+#define DDTP_IOMMU_MODE_1LVL (2 << DDTP_IOMMU_MODE_S)
+#define DDTP_IOMMU_MODE_2LVL (3 << DDTP_IOMMU_MODE_S)
+#define DDTP_IOMMU_MODE_3LVL (4 << DDTP_IOMMU_MODE_S)
+#define DDTP_BUSY (1 << 4)
+#define DDTP_PPN_S 10
+#define DDTP_PPN_M (0xfffffffffffULL << DDTP_PPN_S)
+#define RISCV_IOMMU_CQB 0x18 /* Command queue base. */
+#define CQB_LOG2SZ_1_S 0
+#define CQB_LOG2SZ_1_M (0x3f << CQB_LOG2SZ_1_S)
+#define CQB_PPN_S 10
+#define CQB_PPN_M (0xfffffffffffULL << CQB_PPN_S)
+#define RISCV_IOMMU_CQH 0x20
+#define RISCV_IOMMU_CQT 0x24
+#define RISCV_IOMMU_FQB 0x28 /* Fault queue base. */
+#define RISCV_IOMMU_FQH 0x30
+#define RISCV_IOMMU_FQT 0x34
+#define RISCV_IOMMU_PQB 0x38 /* Page queue base. */
+#define RISCV_IOMMU_PQH 0x40
+#define RISCV_IOMMU_PQT 0x44
+#define RISCV_IOMMU_CQCSR 0x48
+#define CQCSR_BUSY (1 << 17) /* Write is observed */
+#define CQCSR_CQON (1 << 16) /* Active */
+#define CQCSR_FENCE_W_IP (1 << 11) /* iofence.c completed */
+#define CQCSR_CMD_ILL (1 << 10) /* Illegal command */
+#define CQCSR_CMD_TO (1 << 9) /* Timeout */
+#define CQCSR_CQMF (1 << 8) /* Memory Fault */
+#define CQCSR_CIE (1 << 1) /* Interrupt Enable */
+#define CQCSR_CQEN (1 << 0) /* Enable */
+#define RISCV_IOMMU_FQCSR 0x4C
+#define FQCSR_BUSY (1 << 17) /* Write is observed */
+#define FQCSR_FQON (1 << 16) /* Active */
+#define FQCSR_FQOF (1 << 9) /* Overflow */
+#define FQCSR_FQMF (1 << 8) /* Memory Fault */
+#define FQCSR_FIE (1 << 1) /* Interrupt Enable */
+#define FQCSR_FQEN (1 << 0) /* Enable */
+#define RISCV_IOMMU_PQCSR 0x50
+#define PQCSR_BUSY (1 << 17) /* Write is observed */
+#define PQCSR_PQON (1 << 16) /* Active */
+#define PQCSR_PQOF (1 << 9) /* Overflow */
+#define PQCSR_PQMF (1 << 8) /* Memory Fault */
+#define PQCSR_PIE (1 << 1) /* Interrupt Enable */
+#define PQCSR_PQEN (1 << 0) /* Enable */
+#define RISCV_IOMMU_IPSR 0x54
+#define IPSR_CIP (1 << 0) /* Command queue interrupt pending */
+#define IPSR_FIP (1 << 1) /* Fault queue interrupt pending */
+#define IPSR_PMIP (1 << 2) /* Performance monitoring int pend */
+#define IPSR_PIP (1 << 3) /* Page queue interrupt pending */
+
+#define RISCV_IOMMU_IOCOUNTOVF 0x0058
+#define RISCV_IOMMU_IOCOUNTINH 0x005C
+
+#define RISCV_IOMMU_IOHPMCYCLES 0x0060
+#define RISCV_IOMMU_IOHPMCTR_BASE 0x0068
+#define RISCV_IOMMU_IOHPMCTR(_n) (RISCV_IOMMU_IOHPMCTR_BASE + ((_n) * 0x8))
+#define RISCV_IOMMU_IOHPMEVT_BASE 0x0160
+#define RISCV_IOMMU_IOHPMEVT(_n) (RISCV_IOMMU_IOHPMEVT_BASE + ((_n) * 0x8))
+#define RISCV_IOMMU_TR_REQ_IOVA 0x0258
+#define RISCV_IOMMU_TR_REQ_CTL 0x0260
+#define RISCV_IOMMU_TR_RESPONSE 0x0268
+#define RISCV_IOMMU_ICVEC 0x02F8
+
+#define RISCV_IOMMU_LOCK(_sc) mtx_lock(&(_sc)->mtx)
+#define RISCV_IOMMU_UNLOCK(_sc) mtx_unlock(&(_sc)->mtx)
+
+DECLARE_CLASS(riscv_iommu_driver);
+
+MALLOC_DECLARE(M_IOMMU);
+
+struct riscv_iommu_unit {
+ struct iommu_unit iommu;
+ LIST_HEAD(, riscv_iommu_domain) domain_list;
+ LIST_ENTRY(riscv_iommu_unit) next;
+ device_t dev;
+ intptr_t xref;
+};
+
+struct riscv_iommu_domain {
+ struct iommu_domain iodom;
+ LIST_HEAD(, riscv_iommu_ctx) ctx_list;
+ LIST_ENTRY(riscv_iommu_domain) next;
+ u_int entries_cnt;
+ struct riscv_iommu_cd *cd;
+ struct riscv_iommu_pmap p;
+ uint16_t pscid;
+};
+
+struct riscv_iommu_ctx {
+ struct iommu_ctx ioctx;
+ struct riscv_iommu_domain *domain;
+ LIST_ENTRY(riscv_iommu_ctx) next;
+ device_t dev;
+ bool bypass;
+ int did;
+ uint16_t vendor;
+ uint16_t device;
+ u_int refcnt;
+};
+
+struct riscv_iommu_queue_local_copy {
+ union {
+ uint64_t val;
+ struct {
+ uint32_t head;
+ uint32_t tail;
+ };
+ };
+};
+
+struct riscv_iommu_queue {
+ struct riscv_iommu_queue_local_copy lc;
+ vm_paddr_t paddr;
+ void *vaddr;
+ uint64_t mask;
+ uint32_t head_off;
+ uint32_t tail_off;
+ int size_log2;
+ uint64_t base;
+ uint64_t csr;
+ int idx;
+ uint8_t entry_size;
+};
+
+struct l1_desc {
+ uint8_t span;
+ void *va;
+ vm_paddr_t pa;
+};
+
+/* Base-format device-context. */
+struct riscv_iommu_dc_base {
+ uint64_t tc; /* Translation control */
+#define DC_TC_V (1 << 0)
+#define DC_TC_EN_ATS (1 << 1)
+#define DC_TC_EN_PRI (1 << 2)
+#define DC_TC_T2GPA (1 << 3)
+#define DC_TC_DTF (1 << 4)
+#define DC_TC_PDTV (1 << 5)
+#define DC_TC_PRPR (1 << 6)
+#define DC_TC_GADE (1 << 7)
+#define DC_TC_SADE (1 << 8)
+#define DC_TC_DPE (1 << 9)
+#define DC_TC_SBE (1 << 10)
+#define DC_TC_SXL (1 << 11)
+ uint64_t iohgatp; /* IO Hyp guest address translation */
+ uint64_t ta; /* Translation attributes */
+#define DC_TA_V (1 << 0)
+#define DC_TA_ENS (1 << 1)
+#define DC_TA_SUM (1 << 2)
+#define DC_TA_PSCID_S 12
+#define DC_TA_PSCID_M (0xfffff << DC_TA_PSCID_S)
+ uint64_t fsc; /* First-stage-context */
+};
+
+/* Extended-format device-context. */
+struct riscv_iommu_dc {
+ struct riscv_iommu_dc_base base;
+ uint64_t msiptp; /* MSI page table pointer */
+ uint64_t msi_addr_mask;
+ uint64_t msi_addr_pattern;
+ uint64_t _reserved;
+};
+
+#define DC_NON_LEAF_ENTRY_PPN_S 10
+#define DC_NON_LEAF_ENTRY_VALID (1 << 0)
+
+struct riscv_iommu_ddt {
+ void *vaddr;
+ uint64_t base;
+ uint32_t base_cfg;
+ uint32_t num_top_entries;
+ struct l1_desc *l1;
+ struct riscv_iommu_dc *dc;
+};
+
+struct riscv_iommu_softc {
+ device_t dev;
+ intptr_t xref;
+ struct riscv_iommu_unit unit;
+ struct resource *res[5];
+ void *intr_cookie[4];
+ struct riscv_iommu_queue cq;
+ struct riscv_iommu_queue fq;
+ struct riscv_iommu_queue pq;
+ struct riscv_iommu_ddt ddt;
+ struct mtx mtx;
+ uint32_t l0_did_bits;
+ uint32_t dc_dwords;
+
+ /* PSCID management. */
+ bitstr_t *pscid_set;
+ int pscid_set_size;
+ struct mtx pscid_set_mutex;
+ uint32_t pscid_bits;
+
+ enum pmap_mode pm_mode;
+ int iommu_mode;
+};
+
+/*
+ * Command queue request.
+ */
+struct riscv_iommu_command {
+ uint64_t dword0;
+ uint64_t dword1;
+};
+
+enum riscv_iommu_fq_causes {
+ FQ_CAUSE_INST_FAULT = 1,
+ FQ_CAUSE_RD_ADDR_MISALIGNED = 4,
+ FQ_CAUSE_RD_FAULT = 5,
+ FQ_CAUSE_WR_ADDR_MISALIGNED = 6,
+ FQ_CAUSE_WR_FAULT = 7,
+ FQ_CAUSE_INST_FAULT_S = 12,
+ FQ_CAUSE_RD_FAULT_S = 13,
+ FQ_CAUSE_WR_FAULT_S = 15,
+ FQ_CAUSE_INST_FAULT_VS = 20,
+ FQ_CAUSE_RD_FAULT_VS = 21,
+ FQ_CAUSE_WR_FAULT_VS = 23,
+ FQ_CAUSE_DMA_DISABLED = 256,
+ FQ_CAUSE_DDT_LOAD_FAULT = 257,
+ FQ_CAUSE_DDT_INVALID = 258,
+ FQ_CAUSE_DDT_MISCONFIGURED = 259,
+ FQ_CAUSE_TR_TYPE_DISALLOWED = 260,
+ FQ_CAUSE_MSI_LOAD_FAULT = 261,
+ FQ_CAUSE_MSI_INVALID = 262,
+ FQ_CAUSE_MSI_MISCONFIGURED = 263,
+ FQ_CAUSE_MRIF_FAULT = 264,
+ FQ_CAUSE_PDT_LOAD_FAULT = 265,
+ FQ_CAUSE_PDT_INVALID = 266,
+ FQ_CAUSE_PDT_MISCONFIGURED = 267,
+ FQ_CAUSE_DDT_CORRUPTED = 268,
+ FQ_CAUSE_PDT_CORRUPTED = 269,
+ FQ_CAUSE_MSI_PT_CORRUPTED = 270,
+ FQ_CAUSE_MRIF_CORRUPTED = 271,
+ FQ_CAUSE_INTERNAL_DP_ERROR = 272,
+ FQ_CAUSE_MSI_WR_FAULT = 273,
+ FQ_CAUSE_PT_CORRUPTED = 274,
+};
+
+/*
+ * Fault queue record.
+ */
+struct riscv_iommu_fq_record {
+ uint64_t hdr;
+#define FQR_HDR_CAUSE_S 0
+#define FQR_HDR_CAUSE_M (0xfff << FQR_HDR_CAUSE_S)
+#define FQR_HDR_PID_S 12
+#define FQR_HDR_PID_M (0xfffffULL << FQR_HDR_PID_S)
+#define FQR_HDR_PV (1ULL << 32)
+#define FQR_HDR_PRIV (1ULL << 33)
+#define FQR_HDR_TTYP_S 34ULL
+#define FQR_HDR_TTYP_M (0x3fULL << FQR_HDR_TTYP_S)
+#define FQR_HDR_DID_S 40ULL
+#define FQR_HDR_DID_M (0xffffffULL << FQR_HDR_DID_S)
+ uint32_t custom;
+ uint32_t reserved;
+ uint64_t iotval;
+ uint64_t iotval2;
+};
+
+#define COMMAND_OPCODE_S 0
+#define COMMAND_OPCODE_IOTINVAL (1 << COMMAND_OPCODE_S)
+#define COMMAND_OPCODE_IOFENCE (2 << COMMAND_OPCODE_S)
+#define COMMAND_OPCODE_IODIR (3 << COMMAND_OPCODE_S)
+#define COMMAND_OPCODE_ATS (4 << COMMAND_OPCODE_S)
+#define COMMAND_OPCODE_FUNC_S 7
+#define COMMAND_OPCODE_FUNC_M (0x3 << COMMAND_OPCODE_FUNC_S)
+#define FUNC_IODIR_INVAL_DDT (0 << COMMAND_OPCODE_FUNC_S)
+#define FUNC_IODIR_INVAL_PDT (1 << COMMAND_OPCODE_FUNC_S)
+#define FUNC_IODIR_PID_S 12
+#define FUNC_IODIR_DV (1ULL << 33) /* DID Valid */
+#define FUNC_IODIR_DID_S 40ULL
+/* dword0 */
+#define FUNC_IOTINVAL_VMA (0 << COMMAND_OPCODE_FUNC_S)
+#define FUNC_IOTINVAL_GVMA (1 << COMMAND_OPCODE_FUNC_S)
+#define FUNC_IOTINVAL_AV (1 << 10) /* Address Valid */
+#define FUNC_IOTINVAL_PSCID_S 12 /* Process-Soft-Context ID */
+#define FUNC_IOTINVAL_PSCV (1ULL << 32) /* PSCID Valid */
+#define FUNC_IOTINVAL_GV (1ULL << 33) /* GSCID Valid */
+#define FUNC_IOTINVAL_GSCID_S 44 /* Guest-Soft-Context ID */
+/* dword1 */
+#define FUNC_IOTINVAL_ADDR_S 10
+#define FUNC_IOFENCE_FUNC_C (0 << 7)
+#define FUNC_IOFENCE_AV (1 << 10)
+#define FUNC_IOFENCE_WSI (1 << 11)
+#define FUNC_IOFENCE_PR (1 << 12)
+#define FUNC_IOFENCE_PW (1 << 13)
+#define FUNC_IOFENCE_DATA_S 32ULL
+
+int riscv_iommu_attach(device_t dev);
+struct riscv_iommu_ctx *riscv_iommu_ctx_lookup_by_did(device_t dev, u_int did);
+
+#endif /* _RISCV_IOMMU_IOMMU_H_ */
diff --git a/sys/riscv/iommu/iommu_fdt.c b/sys/riscv/iommu/iommu_fdt.c
new file mode 100644
index 000000000000..99fb41d55f8c
--- /dev/null
+++ b/sys/riscv/iommu/iommu_fdt.c
@@ -0,0 +1,145 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2026 Ruslan Bukin <br@bsdpad.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/bitstring.h>
+#include <sys/kernel.h>
+#include <sys/rman.h>
+#include <sys/sysctl.h>
+#include <sys/tree.h>
+#include <sys/taskqueue.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/iommu/iommu.h>
+#include <riscv/iommu/iommu_pmap.h>
+#include <riscv/iommu/iommu.h>
+#include <riscv/iommu/iommu_frontend.h>
+
+static struct ofw_compat_data compat_data[] = {
+ { "riscv,iommu", 1 },
+ { NULL, 0 }
+};
+
+static struct resource_spec riscv_iommu_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 0, RF_ACTIVE }, /* CQ */
+ { SYS_RES_IRQ, 1, RF_ACTIVE }, /* FQ */
+ { SYS_RES_IRQ, 2, RF_ACTIVE }, /* PM */
+ { SYS_RES_IRQ, 3, RF_ACTIVE }, /* PQ */
+ RESOURCE_SPEC_END
+};
+
+static int
+riscv_iommu_fdt_probe(device_t dev)
+{
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "RISC-V IOMMU");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+riscv_iommu_fdt_attach(device_t dev)
+{
+ struct riscv_iommu_softc *sc;
+ struct riscv_iommu_unit *unit;
+ struct iommu_unit *iommu;
+ phandle_t node;
+ int error;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ node = ofw_bus_get_node(dev);
+
+ error = bus_alloc_resources(dev, riscv_iommu_spec, sc->res);
+ if (error) {
+ device_printf(dev, "could not allocate resources\n");
+ goto error;
+ }
+
+ error = riscv_iommu_attach(dev);
+ if (error != 0) {
+ device_printf(dev, "Failed to attach. Error %d\n", error);
+ goto error;
+ }
+
+ unit = &sc->unit;
+ unit->dev = dev;
+
+ iommu = &unit->iommu;
+ iommu->dev = dev;
+
+ LIST_INIT(&unit->domain_list);
+
+ sc->xref = OF_xref_from_node(node);
+
+ error = iommu_register(iommu);
+ if (error) {
+ device_printf(dev, "Failed to register RISC-V IOMMU.\n");
+ goto error;
+ }
+
+ return (0);
+
+error:
+ bus_release_resources(dev, riscv_iommu_spec, sc->res);
+
+ return (error);
+}
+
+static device_method_t riscv_iommu_fdt_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, riscv_iommu_fdt_probe),
+ DEVMETHOD(device_attach, riscv_iommu_fdt_attach),
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_1(riscv_iommu, riscv_iommu_fdt_driver, riscv_iommu_fdt_methods,
+ sizeof(struct riscv_iommu_softc), riscv_iommu_driver);
+EARLY_DRIVER_MODULE(riscv_iommu, simplebus, riscv_iommu_fdt_driver, 0, 0,
+ BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
diff --git a/sys/riscv/iommu/iommu_frontend.c b/sys/riscv/iommu/iommu_frontend.c
new file mode 100644
index 000000000000..1de8b3623987
--- /dev/null
+++ b/sys/riscv/iommu/iommu_frontend.c
@@ -0,0 +1,505 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2026 Ruslan Bukin <br@bsdpad.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "opt_platform.h"
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/memdesc.h>
+#include <sys/tree.h>
+#include <sys/taskqueue.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/sx.h>
+#include <sys/sysctl.h>
+#include <vm/vm.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <machine/bus.h>
+#include <dev/iommu/busdma_iommu.h>
+#include <machine/vmparam.h>
+
+#ifdef FDT
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#endif
+
+#include "iommu_frontend.h"
+#include "iommu_if.h"
+
+static MALLOC_DEFINE(M_IOMMU, "IOMMU", "IOMMU framework");
+
+#define IOMMU_LIST_LOCK() sx_xlock(&iommu_sx)
+#define IOMMU_LIST_UNLOCK() sx_xunlock(&iommu_sx)
+#define IOMMU_LIST_ASSERT_LOCKED() sx_assert(&iommu_sx, SA_XLOCKED)
+
+#define dprintf(fmt, ...)
+
+static struct sx iommu_sx;
+
+struct iommu_entry {
+ struct iommu_unit *iommu;
+ LIST_ENTRY(iommu_entry) next;
+};
+static LIST_HEAD(, iommu_entry) iommu_list = LIST_HEAD_INITIALIZER(iommu_list);
+
+static int
+iommu_domain_unmap_buf(struct iommu_domain *iodom,
+ struct iommu_map_entry *entry, int flags)
+{
+ struct iommu_unit *iommu;
+ int error;
+
+ iommu = iodom->iommu;
+ error = IOMMU_UNMAP(iommu->dev, iodom, entry->start, entry->end -
+ entry->start);
+ return (error);
+}
+
+static int
+iommu_domain_map_buf(struct iommu_domain *iodom, struct iommu_map_entry *entry,
+ vm_page_t *ma, uint64_t eflags, int flags)
+{
+ struct iommu_unit *iommu;
+ vm_prot_t prot;
+ vm_offset_t va;
+ int error;
+
+ dprintf("%s: base %lx, size %lx\n", __func__, base, size);
+
+ prot = 0;
+ if (eflags & IOMMU_MAP_ENTRY_READ)
+ prot |= VM_PROT_READ;
+ if (eflags & IOMMU_MAP_ENTRY_WRITE)
+ prot |= VM_PROT_WRITE;
+
+ va = entry->start;
+ iommu = iodom->iommu;
+ error = IOMMU_MAP(iommu->dev, iodom, va, ma, entry->end -
+ entry->start, prot);
+ return (error);
+}
+
+static const struct iommu_domain_map_ops domain_map_ops = {
+ .map = iommu_domain_map_buf,
+ .unmap = iommu_domain_unmap_buf,
+};
+
+static struct iommu_domain *
+iommu_domain_alloc(struct iommu_unit *iommu)
+{
+ struct iommu_domain *iodom;
+
+ iodom = IOMMU_DOMAIN_ALLOC(iommu->dev, iommu);
+ if (iodom == NULL)
+ return (NULL);
+
+ KASSERT(iodom->end != 0, ("domain end is not set"));
+
+ iommu_domain_init(iommu, iodom, &domain_map_ops);
+ iodom->iommu = iommu;
+ iommu_gas_init_domain(iodom);
+
+ return (iodom);
+}
+
+static int
+iommu_domain_free(struct iommu_domain *iodom)
+{
+ struct iommu_unit *iommu;
+
+ iommu = iodom->iommu;
+
+ IOMMU_LOCK(iommu);
+
+ if ((iodom->flags & IOMMU_DOMAIN_GAS_INITED) != 0) {
+ IOMMU_DOMAIN_LOCK(iodom);
+ iommu_gas_fini_domain(iodom);
+ IOMMU_DOMAIN_UNLOCK(iodom);
+ }
+
+ iommu_domain_fini(iodom);
+
+ IOMMU_DOMAIN_FREE(iommu->dev, iodom);
+ IOMMU_UNLOCK(iommu);
+
+ return (0);
+}
+
+static void
+iommu_tag_init(struct iommu_domain *iodom, struct bus_dma_tag_iommu *t)
+{
+ bus_addr_t maxaddr;
+
+ maxaddr = MIN(iodom->end, BUS_SPACE_MAXADDR);
+
+ t->common.impl = &bus_dma_iommu_impl;
+ t->common.alignment = 1;
+ t->common.boundary = 0;
+ t->common.lowaddr = maxaddr;
+ t->common.highaddr = maxaddr;
+ t->common.maxsize = maxaddr;
+ t->common.nsegments = BUS_SPACE_UNRESTRICTED;
+ t->common.maxsegsz = maxaddr;
+}
+
+static struct iommu_ctx *
+iommu_ctx_alloc(device_t requester, struct iommu_domain *iodom, bool disabled)
+{
+ struct iommu_unit *iommu;
+ struct iommu_ctx *ioctx;
+
+ iommu = iodom->iommu;
+
+ ioctx = IOMMU_CTX_ALLOC(iommu->dev, iodom, requester, disabled);
+ if (ioctx == NULL)
+ return (NULL);
+
+ ioctx->domain = iodom;
+
+ return (ioctx);
+}
+
+static int
+iommu_ctx_init(device_t requester, struct iommu_ctx *ioctx)
+{
+ struct bus_dma_tag_iommu *tag;
+ struct iommu_domain *iodom;
+ struct iommu_unit *iommu;
+ int error;
+
+ iodom = ioctx->domain;
+ iommu = iodom->iommu;
+
+ error = IOMMU_CTX_INIT(iommu->dev, ioctx);
+ if (error)
+ return (error);
+
+ tag = ioctx->tag = malloc(sizeof(struct bus_dma_tag_iommu),
+ M_DEVBUF, M_WAITOK | M_ZERO);
+ tag->owner = requester;
+ tag->ctx = ioctx;
+ tag->ctx->domain = iodom;
+
+ iommu_tag_init(iodom, tag);
+
+ return (error);
+}
+
+static struct iommu_unit *
+iommu_lookup(device_t dev)
+{
+ struct iommu_entry *entry;
+ struct iommu_unit *iommu;
+
+ IOMMU_LIST_LOCK();
+ LIST_FOREACH(entry, &iommu_list, next) {
+ iommu = entry->iommu;
+ if (iommu->dev == dev) {
+ IOMMU_LIST_UNLOCK();
+ return (iommu);
+ }
+ }
+ IOMMU_LIST_UNLOCK();
+
+ return (NULL);
+}
+
+#ifdef FDT
+struct iommu_ctx *
+iommu_get_ctx_ofw(device_t dev, int channel)
+{
+ struct iommu_domain *iodom;
+ struct iommu_unit *iommu;
+ struct iommu_ctx *ioctx;
+ phandle_t node, parent;
+ device_t iommu_dev;
+ pcell_t *cells;
+ int niommus;
+ int ncells;
+ int error;
+
+ node = ofw_bus_get_node(dev);
+ if (node <= 0) {
+ device_printf(dev,
+ "%s called on not ofw based device.\n", __func__);
+ return (NULL);
+ }
+
+ error = ofw_bus_parse_xref_list_get_length(node,
+ "iommus", "#iommu-cells", &niommus);
+ if (error) {
+ device_printf(dev, "%s can't get iommu list.\n", __func__);
+ return (NULL);
+ }
+
+ if (niommus == 0) {
+ device_printf(dev, "%s iommu list is empty.\n", __func__);
+ return (NULL);
+ }
+
+ error = ofw_bus_parse_xref_list_alloc(node, "iommus", "#iommu-cells",
+ channel, &parent, &ncells, &cells);
+ if (error != 0) {
+ device_printf(dev, "%s can't get iommu device xref.\n",
+ __func__);
+ return (NULL);
+ }
+
+ iommu_dev = OF_device_from_xref(parent);
+ if (iommu_dev == NULL) {
+ device_printf(dev, "%s can't get iommu device.\n", __func__);
+ return (NULL);
+ }
+
+ iommu = iommu_lookup(iommu_dev);
+ if (iommu == NULL) {
+ device_printf(dev, "%s can't lookup iommu.\n", __func__);
+ return (NULL);
+ }
+
+ /*
+ * In our current configuration we have a domain per each ctx,
+ * so allocate a domain first.
+ */
+ iodom = iommu_domain_alloc(iommu);
+ if (iodom == NULL) {
+ device_printf(dev, "%s can't allocate domain.\n", __func__);
+ return (NULL);
+ }
+
+ ioctx = iommu_ctx_alloc(dev, iodom, false);
+ if (ioctx == NULL) {
+ iommu_domain_free(iodom);
+ return (NULL);
+ }
+
+ ioctx->domain = iodom;
+
+ error = IOMMU_OFW_MD_DATA(iommu->dev, ioctx, cells, ncells);
+ if (error) {
+ device_printf(dev, "%s can't set MD data\n", __func__);
+ return (NULL);
+ }
+
+ error = iommu_ctx_init(dev, ioctx);
+ if (error) {
+ IOMMU_CTX_FREE(iommu->dev, ioctx);
+ iommu_domain_free(iodom);
+ return (NULL);
+ }
+
+ return (ioctx);
+}
+#endif
+
+struct iommu_ctx *
+iommu_get_ctx(struct iommu_unit *iommu, device_t requester,
+ uint16_t rid, bool disabled, bool rmrr)
+{
+ struct iommu_domain *iodom;
+ struct iommu_ctx *ioctx;
+ int error;
+
+ IOMMU_LOCK(iommu);
+ ioctx = IOMMU_CTX_LOOKUP(iommu->dev, requester);
+ if (ioctx) {
+ IOMMU_UNLOCK(iommu);
+ return (ioctx);
+ }
+ IOMMU_UNLOCK(iommu);
+
+ /*
+ * In our current configuration we have a domain per each ctx.
+ * So allocate a domain first.
+ */
+ iodom = iommu_domain_alloc(iommu);
+ if (iodom == NULL)
+ return (NULL);
+
+ ioctx = iommu_ctx_alloc(requester, iodom, disabled);
+ if (ioctx == NULL) {
+ iommu_domain_free(iodom);
+ return (NULL);
+ }
+
+ error = iommu_ctx_init(requester, ioctx);
+ if (error) {
+ IOMMU_CTX_FREE(iommu->dev, ioctx);
+ iommu_domain_free(iodom);
+ return (NULL);
+ }
+
+ return (ioctx);
+}
+
+void
+iommu_free_ctx_locked(struct iommu_unit *iommu, struct iommu_ctx *ioctx)
+{
+ struct iommu_domain *domain;
+ bool released;
+ int error;
+
+ IOMMU_ASSERT_LOCKED(iommu);
+
+ domain = ioctx->domain;
+
+ released = IOMMU_CTX_FREE(iommu->dev, ioctx);
+ IOMMU_UNLOCK(iommu);
+
+ if (released) {
+ /* Since we have a domain per each ctx, remove it too. */
+ error = iommu_domain_free(domain);
+ if (error)
+ device_printf(iommu->dev, "Could not free a domain\n");
+ }
+}
+
+static void
+iommu_domain_free_entry(struct iommu_map_entry *entry, bool free)
+{
+ iommu_gas_free_space(entry);
+
+ if (free)
+ iommu_gas_free_entry(entry);
+ else
+ entry->flags = 0;
+}
+
+void
+iommu_domain_unload(struct iommu_domain *iodom,
+ struct iommu_map_entries_tailq *entries, bool cansleep)
+{
+ struct iommu_map_entry *entry, *entry1;
+ int error __diagused;
+
+ TAILQ_FOREACH_SAFE(entry, entries, dmamap_link, entry1) {
+ KASSERT((entry->flags & IOMMU_MAP_ENTRY_MAP) != 0,
+ ("not mapped entry %p %p", iodom, entry));
+ error = iodom->ops->unmap(iodom, entry,
+ cansleep ? IOMMU_PGF_WAITOK : 0);
+ KASSERT(error == 0, ("unmap %p error %d", iodom, error));
+ TAILQ_REMOVE(entries, entry, dmamap_link);
+ iommu_domain_free_entry(entry, true);
+ }
+
+ if (TAILQ_EMPTY(entries))
+ return;
+
+ panic("entries map is not empty");
+}
+
+int
+iommu_register(struct iommu_unit *iommu)
+{
+ struct iommu_entry *entry;
+
+ mtx_init(&iommu->lock, "IOMMU", NULL, MTX_DEF);
+
+ entry = malloc(sizeof(struct iommu_entry), M_IOMMU, M_WAITOK | M_ZERO);
+ entry->iommu = iommu;
+
+ IOMMU_LIST_LOCK();
+ LIST_INSERT_HEAD(&iommu_list, entry, next);
+ IOMMU_LIST_UNLOCK();
+
+ sysctl_ctx_init(&iommu->sysctl_ctx);
+ iommu_init_busdma(iommu);
+
+ return (0);
+}
+
+int
+iommu_unregister(struct iommu_unit *iommu)
+{
+ struct iommu_entry *entry, *tmp;
+
+ IOMMU_LIST_LOCK();
+ LIST_FOREACH_SAFE(entry, &iommu_list, next, tmp) {
+ if (entry->iommu == iommu) {
+ LIST_REMOVE(entry, next);
+ free(entry, M_IOMMU);
+ }
+ }
+ IOMMU_LIST_UNLOCK();
+
+ iommu_fini_busdma(iommu);
+ sysctl_ctx_free(&iommu->sysctl_ctx);
+
+ mtx_destroy(&iommu->lock);
+
+ return (0);
+}
+
+struct iommu_unit *
+iommu_find(device_t dev, bool verbose)
+{
+ struct iommu_entry *entry;
+ struct iommu_unit *iommu;
+ int error;
+
+ IOMMU_LIST_LOCK();
+ LIST_FOREACH(entry, &iommu_list, next) {
+ iommu = entry->iommu;
+ error = IOMMU_FIND(iommu->dev, dev);
+ if (error == 0) {
+ IOMMU_LIST_UNLOCK();
+ return (entry->iommu);
+ }
+ }
+ IOMMU_LIST_UNLOCK();
+
+ return (NULL);
+}
+
+void
+iommu_unit_pre_instantiate_ctx(struct iommu_unit *unit)
+{
+}
+
+void
+iommu_domain_unload_entry(struct iommu_map_entry *entry, bool free,
+ bool cansleep __unused)
+{
+
+ dprintf("%s\n", __func__);
+
+ iommu_domain_free_entry(entry, free);
+}
+
+static void
+iommu_init(void)
+{
+
+ sx_init(&iommu_sx, "IOMMU list");
+}
+
+SYSINIT(iommu, SI_SUB_DRIVERS, SI_ORDER_FIRST, iommu_init, NULL);
diff --git a/sys/riscv/iommu/iommu_frontend.h b/sys/riscv/iommu/iommu_frontend.h
new file mode 100644
index 000000000000..f42856037383
--- /dev/null
+++ b/sys/riscv/iommu/iommu_frontend.h
@@ -0,0 +1,38 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2026 Ruslan Bukin <br@bsdpad.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _ARM64_IOMMU_IOMMU_H_
+#define _ARM64_IOMMU_IOMMU_H_
+
+#define IOMMU_PAGE_SIZE 4096
+#define IOMMU_PAGE_MASK (IOMMU_PAGE_SIZE - 1)
+
+int iommu_unregister(struct iommu_unit *unit);
+int iommu_register(struct iommu_unit *unit);
+struct iommu_ctx * iommu_get_ctx_ofw(device_t dev, int channel);
+
+#endif /* _ARM64_IOMMU_IOMMU_H_ */
diff --git a/sys/riscv/iommu/iommu_if.m b/sys/riscv/iommu/iommu_if.m
new file mode 100644
index 000000000000..56a04b7b8638
--- /dev/null
+++ b/sys/riscv/iommu/iommu_if.m
@@ -0,0 +1,147 @@
+#-
+# SPDX-License-Identifier: BSD-2-Clause
+#:
+# Copyright (c) 2026 Ruslan Bukin <br@bsdpad.com>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#
+
+#include "opt_platform.h"
+
+#include <sys/types.h>
+#include <sys/taskqueue.h>
+#include <sys/bus.h>
+#include <sys/sysctl.h>
+#include <sys/tree.h>
+#include <vm/vm.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/iommu/iommu.h>
+
+#ifdef FDT
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#endif
+
+INTERFACE iommu;
+
+#
+# Check if the iommu controller dev is responsible to serve traffic
+# for a given child.
+#
+METHOD int find {
+ device_t dev;
+ device_t child;
+};
+
+#
+# Map a virtual address VA to a physical address PA.
+#
+METHOD int map {
+ device_t dev;
+ struct iommu_domain *iodom;
+ vm_offset_t va;
+ vm_page_t *ma;
+ bus_size_t size;
+ vm_prot_t prot;
+};
+
+#
+# Unmap a virtual address VA.
+#
+METHOD int unmap {
+ device_t dev;
+ struct iommu_domain *iodom;
+ vm_offset_t va;
+ bus_size_t size;
+};
+
+#
+# Allocate an IOMMU domain.
+#
+METHOD struct iommu_domain * domain_alloc {
+ device_t dev;
+ struct iommu_unit *iommu;
+};
+
+#
+# Release all the resources held by IOMMU domain.
+#
+METHOD void domain_free {
+ device_t dev;
+ struct iommu_domain *iodom;
+};
+
+#
+# Find a domain allocated for a dev.
+#
+METHOD struct iommu_domain * domain_lookup {
+ device_t dev;
+};
+
+#
+# Find an allocated context for a device.
+#
+METHOD struct iommu_ctx * ctx_lookup {
+ device_t dev;
+ device_t child;
+};
+
+#
+# Allocate a new iommu context.
+#
+METHOD struct iommu_ctx * ctx_alloc {
+ device_t dev;
+ struct iommu_domain *iodom;
+ device_t child;
+ bool disabled;
+};
+
+#
+# Initialize the new iommu context.
+#
+METHOD int ctx_init {
+ device_t dev;
+ struct iommu_ctx *ioctx;
+};
+
+#
+# Free the iommu context.
+#
+METHOD bool ctx_free {
+ device_t dev;
+ struct iommu_ctx *ioctx;
+};
+
+#ifdef FDT
+#
+# Notify controller we have machine-dependent data.
+#
+METHOD int ofw_md_data {
+ device_t dev;
+ struct iommu_ctx *ioctx;
+ pcell_t *cells;
+ int ncells;
+};
+#endif
diff --git a/sys/riscv/iommu/iommu_pci.c b/sys/riscv/iommu/iommu_pci.c
new file mode 100644
index 000000000000..2ec5b2dc95b5
--- /dev/null
+++ b/sys/riscv/iommu/iommu_pci.c
@@ -0,0 +1,172 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2026 Ruslan Bukin <br@bsdpad.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/bitstring.h>
+#include <sys/kernel.h>
+#include <sys/rman.h>
+#include <sys/sysctl.h>
+#include <sys/tree.h>
+#include <sys/taskqueue.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/iommu/iommu.h>
+#include <riscv/iommu/iommu_pmap.h>
+#include <riscv/iommu/iommu.h>
+#include <riscv/iommu/iommu_frontend.h>
+
+#define PCI_DEVICE_ID_REDHAT_RISCV_IOMMU 0x0014
+#define PCI_VENDOR_ID_REDHAT 0x1b36
+#define PCI_DEVICE_ID_RIVOS_RISCV_IOMMU_GA 0x0008
+#define PCI_VENDOR_ID_RIVOS 0x1efd
+
+static int
+iommu_pci_probe(device_t dev)
+{
+ uint16_t vendor_id, device_id;
+
+ vendor_id = pci_get_vendor(dev);
+ device_id = pci_get_device(dev);
+
+ if (vendor_id == PCI_VENDOR_ID_REDHAT &&
+ device_id == PCI_DEVICE_ID_REDHAT_RISCV_IOMMU) {
+ device_set_desc(dev, "RedHat IOMMU");
+ return (BUS_PROBE_DEFAULT);
+ }
+
+ if (vendor_id == PCI_VENDOR_ID_RIVOS &&
+ device_id == PCI_DEVICE_ID_RIVOS_RISCV_IOMMU_GA) {
+ device_set_desc(dev, "Rivos IOMMU");
+ return (BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static int
+iommu_pci_attach(device_t dev)
+{
+ struct riscv_iommu_unit *unit;
+ struct riscv_iommu_softc *sc;
+ struct iommu_unit *iommu;
+ phandle_t node;
+ int count;
+ int error;
+ int rid;
+ int i;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ node = ofw_bus_get_node(dev);
+
+ pci_enable_busmaster(dev);
+
+ rid = PCIR_BAR(0);
+ sc->res[0] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->res[0] == NULL) {
+ device_printf(dev, "couldn't map memory\n");
+ goto error;
+ }
+
+ count = 4;
+ if (pci_alloc_msix(dev, &count) == 0) {
+ for (i = 0; i < 4; i++) {
+ rid = i;
+ sc->res[1 + i] = bus_alloc_resource_any(dev,
+ SYS_RES_IRQ, &rid, RF_ACTIVE);
+ if (sc->res[i + 1] == NULL) {
+ device_printf(dev, "Can't allocate IRQ "
+ " resource.\n");
+ goto error;
+ }
+ }
+ } else
+ device_printf(dev, "Can't allocate MSI-X interrupts."
+ " Ignoring.\n");
+
+ error = riscv_iommu_attach(dev);
+ if (error)
+ goto error;
+
+ unit = &sc->unit;
+ unit->dev = dev;
+
+ iommu = &unit->iommu;
+ iommu->dev = dev;
+
+ LIST_INIT(&unit->domain_list);
+
+ sc->xref = OF_xref_from_node(node);
+
+ error = iommu_register(iommu);
+ if (error) {
+ device_printf(dev, "Failed to register RISC-V IOMMU.\n");
+ goto error;
+ }
+
+ return (0);
+
+error:
+ if (sc->res[0])
+ bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(0),
+ sc->res[0]);
+
+ for (i = 0; i < 4; i++)
+ if (sc->res[i + 1])
+ bus_release_resource(dev, SYS_RES_IRQ, i,
+ sc->res[i + 1]);
+
+ return (error);
+}
+
+static device_method_t riscv_iommu_pci_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, iommu_pci_probe),
+ DEVMETHOD(device_attach, iommu_pci_attach),
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_1(riscv_iommu, riscv_iommu_pci_driver,
+ riscv_iommu_pci_methods, sizeof(struct riscv_iommu_softc),
+ riscv_iommu_driver);
+DRIVER_MODULE(riscv_iommu, pci, riscv_iommu_pci_driver, NULL, NULL);
diff --git a/sys/riscv/iommu/iommu_pmap.c b/sys/riscv/iommu/iommu_pmap.c
new file mode 100644
index 000000000000..751ba4cf1ac3
--- /dev/null
+++ b/sys/riscv/iommu/iommu_pmap.c
@@ -0,0 +1,629 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2026 Ruslan Bukin <br@bsdpad.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/ktr.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/vm_page.h>
+
+#include <riscv/iommu/iommu_pmap.h>
+
+/*
+ * Boundary values for the page table page index space:
+ *
+ * L3 pages: [0, NUL2E)
+ * L2 pages: [NUL2E, NUL2E + NUL1E)
+ * L1 pages: [NUL2E + NUL1E, NUL2E + NUL1E + NUL0E)
+ *
+ * Note that these ranges are used in both SV39 and SV48 mode. In SV39 mode the
+ * ranges are not fully populated since there are at most Ln_ENTRIES^2 L3 pages
+ * in a set of page tables.
+ */
+#define NUL0E Ln_ENTRIES
+#define NUL1E (Ln_ENTRIES * NUL0E)
+#define NUL2E (Ln_ENTRIES * NUL1E)
+
+#define pmap_l1_pindex(v) (NUL2E + ((v) >> L1_SHIFT))
+#define pmap_l2_pindex(v) ((v) >> L2_SHIFT)
+
+#define pmap_clear(pte) pmap_store(pte, 0)
+#define pmap_clear_bits(pte, bits) atomic_clear_64(pte, bits)
+#define pmap_load_store(pte, entry) atomic_swap_64(pte, entry)
+#define pmap_load_clear(pte) pmap_load_store(pte, 0)
+#define pmap_load(pte) atomic_load_64(pte)
+#define pmap_store(pte, entry) atomic_store_64(pte, entry)
+#define pmap_store_bits(pte, bits) atomic_set_64(pte, bits)
+
+#define pmap_l0_index(va) (((va) >> L0_SHIFT) & Ln_ADDR_MASK)
+#define pmap_l1_index(va) (((va) >> L1_SHIFT) & Ln_ADDR_MASK)
+#define pmap_l2_index(va) (((va) >> L2_SHIFT) & Ln_ADDR_MASK)
+#define pmap_l3_index(va) (((va) >> L3_SHIFT) & Ln_ADDR_MASK)
+
+#define PTE_TO_PHYS(pte) \
+ ((((pte) & ~PTE_HI_MASK) >> PTE_PPN0_S) * PAGE_SIZE)
+#define L2PTE_TO_PHYS(l2) \
+ ((((l2) & ~PTE_HI_MASK) >> PTE_PPN1_S) << L2_SHIFT)
+#define L1PTE_TO_PHYS(l1) \
+ ((((l1) & ~PTE_HI_MASK) >> PTE_PPN2_S) << L1_SHIFT)
+#define PTE_TO_VM_PAGE(pte) PHYS_TO_VM_PAGE(PTE_TO_PHYS(pte))
+
+/********************/
+/* Inline functions */
+/********************/
+
+static __inline pd_entry_t *
+pmap_l0(struct riscv_iommu_pmap *pmap, vm_offset_t va)
+{
+ KASSERT(pmap->pm_mode != PMAP_MODE_SV39,
+ ("%s: in SV39 mode", __func__));
+ KASSERT(VIRT_IS_VALID(va),
+ ("%s: malformed virtual address %#lx", __func__, va));
+ return (&pmap->pm_top[pmap_l0_index(va)]);
+}
+
+static __inline pd_entry_t *
+pmap_l0_to_l1(struct riscv_iommu_pmap *pmap, pd_entry_t *l0, vm_offset_t va)
+{
+ vm_paddr_t phys;
+ pd_entry_t *l1;
+
+ KASSERT(pmap->pm_mode != PMAP_MODE_SV39,
+ ("%s: in SV39 mode", __func__));
+ phys = PTE_TO_PHYS(pmap_load(l0));
+ l1 = (pd_entry_t *)PHYS_TO_DMAP(phys);
+
+ return (&l1[pmap_l1_index(va)]);
+}
+
+static __inline pd_entry_t *
+pmap_l1(struct riscv_iommu_pmap *pmap, vm_offset_t va)
+{
+ pd_entry_t *l0;
+
+ KASSERT(VIRT_IS_VALID(va),
+ ("%s: malformed virtual address %#lx", __func__, va));
+ if (pmap->pm_mode == PMAP_MODE_SV39) {
+ return (&pmap->pm_top[pmap_l1_index(va)]);
+ } else {
+ l0 = pmap_l0(pmap, va);
+ if ((pmap_load(l0) & PTE_V) == 0)
+ return (NULL);
+ if ((pmap_load(l0) & PTE_RX) != 0)
+ return (NULL);
+ return (pmap_l0_to_l1(pmap, l0, va));
+ }
+}
+
+static __inline pd_entry_t *
+pmap_l1_to_l2(pd_entry_t *l1, vm_offset_t va)
+{
+ vm_paddr_t phys;
+ pd_entry_t *l2;
+
+ phys = PTE_TO_PHYS(pmap_load(l1));
+ l2 = (pd_entry_t *)PHYS_TO_DMAP(phys);
+
+ return (&l2[pmap_l2_index(va)]);
+}
+
+static __inline pd_entry_t *
+pmap_l2(struct riscv_iommu_pmap *pmap, vm_offset_t va)
+{
+ pd_entry_t *l1;
+
+ l1 = pmap_l1(pmap, va);
+ if (l1 == NULL)
+ return (NULL);
+ if ((pmap_load(l1) & PTE_V) == 0)
+ return (NULL);
+ if ((pmap_load(l1) & PTE_RX) != 0)
+ return (NULL);
+
+ return (pmap_l1_to_l2(l1, va));
+}
+
+static __inline pt_entry_t *
+pmap_l2_to_l3(pd_entry_t *l2, vm_offset_t va)
+{
+ vm_paddr_t phys;
+ pt_entry_t *l3;
+
+ phys = PTE_TO_PHYS(pmap_load(l2));
+ l3 = (pd_entry_t *)PHYS_TO_DMAP(phys);
+
+ return (&l3[pmap_l3_index(va)]);
+}
+
+static __inline pt_entry_t *
+pmap_l3(struct riscv_iommu_pmap *pmap, vm_offset_t va)
+{
+ pd_entry_t *l2;
+
+ l2 = pmap_l2(pmap, va);
+ if (l2 == NULL)
+ return (NULL);
+ if ((pmap_load(l2) & PTE_V) == 0)
+ return (NULL);
+ if ((pmap_load(l2) & PTE_RX) != 0)
+ return (NULL);
+
+ return (pmap_l2_to_l3(l2, va));
+}
+
+static __inline void
+pmap_resident_count_inc(struct riscv_iommu_pmap *pmap, int count)
+{
+
+ PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+ pmap->sp_resident_count += count;
+}
+
+static __inline void
+pmap_resident_count_dec(struct riscv_iommu_pmap *pmap, int count)
+{
+
+ PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+ KASSERT(pmap->sp_resident_count >= count,
+ ("pmap %p resident count underflow %ld %d", pmap,
+ pmap->sp_resident_count, count));
+ pmap->sp_resident_count -= count;
+}
+
+/***************************************************
+ * Page table page management routines.....
+ ***************************************************/
+
+int
+iommu_pmap_pinit(struct riscv_iommu_pmap *pmap, enum pmap_mode pm_mode)
+{
+ vm_paddr_t topphys;
+ vm_page_t m;
+
+ m = vm_page_alloc_noobj(VM_ALLOC_WIRED | VM_ALLOC_ZERO |
+ VM_ALLOC_WAITOK);
+ topphys = VM_PAGE_TO_PHYS(m);
+ pmap->pm_top = (pd_entry_t *)PHYS_TO_DMAP(topphys);
+ pmap->pm_mode = pm_mode;
+
+ switch (pm_mode) {
+ case PMAP_MODE_SV39:
+ pmap->pm_satp = SATP_MODE_SV39;
+ break;
+ case PMAP_MODE_SV48:
+ pmap->pm_satp = SATP_MODE_SV48;
+ break;
+ default:
+ panic("Unknown virtual memory system");
+ };
+
+ pmap->pm_satp |= (topphys >> PAGE_SHIFT);
+
+#ifdef INVARIANTS
+ pmap->sp_resident_count = 0;
+#endif
+
+ mtx_init(&pmap->pm_mtx, "iommu pmap", NULL, MTX_DEF);
+
+ return (1);
+}
+
+/*
+ * Release any resources held by the given physical map.
+ * Called when a pmap initialized by pmap_pinit is being released.
+ * Should only be called if the map contains no valid mappings.
+ */
+void
+iommu_pmap_release(struct riscv_iommu_pmap *pmap)
+{
+ vm_page_t m;
+
+ KASSERT(pmap->sp_resident_count == 0,
+ ("pmap_release: pmap resident count %ld != 0",
+ pmap->sp_resident_count));
+
+ m = PHYS_TO_VM_PAGE(DMAP_TO_PHYS((vm_offset_t)pmap->pm_top));
+ vm_page_unwire_noq(m);
+ vm_page_free_zero(m);
+ mtx_destroy(&pmap->pm_mtx);
+}
+
+/*
+ * This routine is called if the desired page table page does not exist.
+ *
+ * If page table page allocation fails, this routine may sleep before
+ * returning NULL. It sleeps only if a lock pointer was given.
+ *
+ * Note: If a page allocation fails at page table level two or three,
+ * one or two pages may be held during the wait, only to be released
+ * afterwards. This conservative approach is easily argued to avoid
+ * race conditions.
+ */
+static vm_page_t
+_pmap_alloc_l3(struct riscv_iommu_pmap *pmap, vm_pindex_t ptepindex)
+{
+ vm_page_t m, pdpg;
+ pt_entry_t entry;
+ vm_paddr_t phys;
+ pn_t pn;
+
+ PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+
+ /*
+ * Allocate a page table page.
+ */
+ m = vm_page_alloc_noobj(VM_ALLOC_WIRED | VM_ALLOC_ZERO);
+ if (m == NULL) {
+ /*
+ * Indicate the need to retry. While waiting, the page table
+ * page may have been allocated.
+ */
+ return (NULL);
+ }
+ m->pindex = ptepindex;
+
+ /*
+ * Map the pagetable page into the process address space, if
+ * it isn't already there.
+ */
+ pn = VM_PAGE_TO_PHYS(m) >> PAGE_SHIFT;
+ if (ptepindex >= NUL2E + NUL1E) {
+ pd_entry_t *l0;
+ vm_pindex_t l0index;
+
+ KASSERT(pmap->pm_mode != PMAP_MODE_SV39,
+ ("%s: pindex %#lx in SV39 mode", __func__, ptepindex));
+ KASSERT(ptepindex < NUL2E + NUL1E + NUL0E,
+ ("%s: pindex %#lx out of range", __func__, ptepindex));
+
+ l0index = ptepindex - (NUL2E + NUL1E);
+ l0 = &pmap->pm_top[l0index];
+ KASSERT((pmap_load(l0) & PTE_V) == 0,
+ ("%s: L0 entry %#lx is valid", __func__, pmap_load(l0)));
+
+ entry = PTE_V | (pn << PTE_PPN0_S);
+ pmap_store(l0, entry);
+ } else if (ptepindex >= NUL2E) {
+ pd_entry_t *l0, *l1;
+ vm_pindex_t l0index, l1index;
+
+ l1index = ptepindex - NUL2E;
+ if (pmap->pm_mode == PMAP_MODE_SV39) {
+ l1 = &pmap->pm_top[l1index];
+ } else {
+ l0index = l1index >> Ln_ENTRIES_SHIFT;
+ l0 = &pmap->pm_top[l0index];
+ if (pmap_load(l0) == 0) {
+ /* Recurse to allocate the L1 page. */
+ if (_pmap_alloc_l3(pmap,
+ NUL2E + NUL1E + l0index) == NULL)
+ goto fail;
+ phys = PTE_TO_PHYS(pmap_load(l0));
+ } else {
+ phys = PTE_TO_PHYS(pmap_load(l0));
+ pdpg = PHYS_TO_VM_PAGE(phys);
+ pdpg->ref_count++;
+ }
+ l1 = (pd_entry_t *)PHYS_TO_DMAP(phys);
+ l1 = &l1[ptepindex & Ln_ADDR_MASK];
+ }
+ KASSERT((pmap_load(l1) & PTE_V) == 0,
+ ("%s: L1 entry %#lx is valid", __func__, pmap_load(l1)));
+
+ entry = PTE_V | (pn << PTE_PPN0_S);
+ pmap_store(l1, entry);
+ } else {
+ vm_pindex_t l0index, l1index;
+ pd_entry_t *l0, *l1, *l2;
+
+ l1index = ptepindex >> (L1_SHIFT - L2_SHIFT);
+ if (pmap->pm_mode == PMAP_MODE_SV39) {
+ l1 = &pmap->pm_top[l1index];
+ if (pmap_load(l1) == 0) {
+ /* recurse for allocating page dir */
+ if (_pmap_alloc_l3(pmap, NUL2E + l1index)
+ == NULL)
+ goto fail;
+ } else {
+ pdpg = PTE_TO_VM_PAGE(pmap_load(l1));
+ pdpg->ref_count++;
+ }
+ } else {
+ l0index = l1index >> Ln_ENTRIES_SHIFT;
+ l0 = &pmap->pm_top[l0index];
+ if (pmap_load(l0) == 0) {
+ /* Recurse to allocate the L1 entry. */
+ if (_pmap_alloc_l3(pmap, NUL2E + l1index)
+ == NULL)
+ goto fail;
+ phys = PTE_TO_PHYS(pmap_load(l0));
+ l1 = (pd_entry_t *)PHYS_TO_DMAP(phys);
+ l1 = &l1[l1index & Ln_ADDR_MASK];
+ } else {
+ phys = PTE_TO_PHYS(pmap_load(l0));
+ l1 = (pd_entry_t *)PHYS_TO_DMAP(phys);
+ l1 = &l1[l1index & Ln_ADDR_MASK];
+ if (pmap_load(l1) == 0) {
+ /* Recurse to allocate the L2 page. */
+ if (_pmap_alloc_l3(pmap,
+ NUL2E + l1index) == NULL)
+ goto fail;
+ } else {
+ pdpg = PTE_TO_VM_PAGE(pmap_load(l1));
+ pdpg->ref_count++;
+ }
+ }
+ }
+
+ phys = PTE_TO_PHYS(pmap_load(l1));
+ l2 = (pd_entry_t *)PHYS_TO_DMAP(phys);
+ l2 = &l2[ptepindex & Ln_ADDR_MASK];
+ KASSERT((pmap_load(l2) & PTE_V) == 0,
+ ("%s: L2 entry %#lx is valid", __func__, pmap_load(l2)));
+
+ entry = PTE_V | (pn << PTE_PPN0_S);
+ pmap_store(l2, entry);
+ }
+
+ pmap_resident_count_inc(pmap, 1);
+
+ return (m);
+
+fail:
+ vm_page_unwire_noq(m);
+ vm_page_free_zero(m);
+ return (NULL);
+}
+
+/*
+ * Remove a single IOMMU entry.
+ */
+int
+iommu_pmap_remove(struct riscv_iommu_pmap *pmap, vm_offset_t va)
+{
+ pt_entry_t *l3;
+ int rc;
+
+ PMAP_LOCK(pmap);
+
+ l3 = pmap_l3(pmap, va);
+ if (l3 != NULL) {
+ pmap_resident_count_dec(pmap, 1);
+ pmap_clear(l3);
+ rc = KERN_SUCCESS;
+ } else
+ rc = KERN_FAILURE;
+
+ PMAP_UNLOCK(pmap);
+
+ return (rc);
+}
+
+/* Add a single IOMMU entry. This function does not sleep. */
+int
+iommu_pmap_enter(struct riscv_iommu_pmap *pmap, vm_offset_t va, vm_paddr_t pa,
+ vm_prot_t prot, u_int flags)
+{
+ pd_entry_t *l2, l2e;
+ pt_entry_t new_l3;
+ pt_entry_t *l3;
+ vm_page_t mpte;
+ pn_t pn;
+ int rv;
+
+ pn = (pa / PAGE_SIZE);
+
+ new_l3 = PTE_V | PTE_R | PTE_A;
+ if (prot & VM_PROT_EXECUTE)
+ new_l3 |= PTE_X;
+ if (flags & VM_PROT_WRITE)
+ new_l3 |= PTE_D;
+ if (prot & VM_PROT_WRITE)
+ new_l3 |= PTE_W;
+ if (va < VM_MAX_USER_ADDRESS)
+ new_l3 |= PTE_U;
+
+ new_l3 |= (pn << PTE_PPN0_S);
+ new_l3 |= PTE_MA_IO;
+
+ /*
+ * Set modified bit gratuitously for writeable mappings if
+ * the page is unmanaged. We do not want to take a fault
+ * to do the dirty bit accounting for these mappings.
+ */
+ if (prot & VM_PROT_WRITE)
+ new_l3 |= PTE_D;
+
+ CTR2(KTR_PMAP, "pmap_enter: %.16lx -> %.16lx", va, pa);
+
+ mpte = NULL;
+ PMAP_LOCK(pmap);
+
+ l2 = pmap_l2(pmap, va);
+ if (l2 != NULL && ((l2e = pmap_load(l2)) & PTE_V) != 0 &&
+ ((l2e & PTE_RWX) == 0)) {
+ l3 = pmap_l2_to_l3(l2, va);
+ } else if (va < VM_MAXUSER_ADDRESS) {
+ mpte = _pmap_alloc_l3(pmap, pmap_l2_pindex(va));
+ if (mpte == NULL) {
+ CTR0(KTR_PMAP, "pmap_enter: mpte == NULL");
+ rv = KERN_RESOURCE_SHORTAGE;
+ goto out;
+ }
+ l3 = pmap_l3(pmap, va);
+ } else
+ panic("pmap_enter: missing L3 table for kernel va %#lx", va);
+
+ KASSERT((pmap_load(l3) & PTE_V) == 0, ("l3 is valid"));
+
+ pmap_store(l3, new_l3);
+ pmap_resident_count_inc(pmap, 1);
+
+ rv = KERN_SUCCESS;
+out:
+ PMAP_UNLOCK(pmap);
+
+ return (rv);
+}
+
+static void
+iommu_pmap_remove_pages_sv48(struct riscv_iommu_pmap *pmap)
+{
+ pd_entry_t l0e, *l1, l1e, *l2, l2e, *l3, l3e;
+ vm_paddr_t pa0, pa1, pa;
+ vm_page_t m0, m1, m;
+ int i, j, k, l;
+
+ PMAP_LOCK(pmap);
+
+ for (i = 0; i < Ln_ENTRIES; i++) {
+ l0e = pmap->pm_top[i];
+ if ((l0e & PTE_V) == 0)
+ continue;
+ pa0 = PTE_TO_PHYS(l0e);
+ m0 = PHYS_TO_VM_PAGE(pa0);
+ l1 = (pd_entry_t *)PHYS_TO_DMAP(pa0);
+
+ for (j = 0; j < Ln_ENTRIES; j++) {
+ l1e = l1[j];
+ if ((l1e & PTE_V) == 0)
+ continue;
+ pa1 = PTE_TO_PHYS(l1e);
+ m1 = PHYS_TO_VM_PAGE(pa1);
+ l2 = (pd_entry_t *)PHYS_TO_DMAP(pa1);
+
+ for (k = 0; k < Ln_ENTRIES; k++) {
+ l2e = l2[k];
+ if ((l2e & PTE_V) == 0)
+ continue;
+ pa = PTE_TO_PHYS(l2e);
+ m = PHYS_TO_VM_PAGE(pa);
+ l3 = (pt_entry_t *)PHYS_TO_DMAP(pa);
+
+ for (l = 0; l < Ln_ENTRIES; l++) {
+ l3e = l3[l];
+ if ((l3e & PTE_V) == 0)
+ continue;
+ panic("%s: l3e found (idx %d %d %d %d)",
+ __func__, i, j, k, l);
+ }
+
+ vm_page_unwire_noq(m1);
+ vm_page_unwire_noq(m);
+ pmap_resident_count_dec(pmap, 1);
+ vm_page_free(m);
+ pmap_clear(&l2[k]);
+ }
+
+ vm_page_unwire_noq(m0);
+ pmap_resident_count_dec(pmap, 1);
+ vm_page_free(m1);
+ pmap_clear(&l1[j]);
+ }
+
+ pmap_resident_count_dec(pmap, 1);
+ vm_page_free(m0);
+ pmap_clear(&pmap->pm_top[i]);
+ }
+
+ KASSERT(pmap->sp_resident_count == 0,
+ ("Invalid resident count %jd", pmap->sp_resident_count));
+
+ PMAP_UNLOCK(pmap);
+}
+
+static void
+iommu_pmap_remove_pages_sv39(struct riscv_iommu_pmap *pmap)
+{
+ pd_entry_t l1e, *l2, l2e, *l3, l3e;
+ vm_paddr_t pa1, pa;
+ vm_page_t m1, m;
+ int j, k, l;
+
+ PMAP_LOCK(pmap);
+
+ for (j = 0; j < Ln_ENTRIES; j++) {
+ l1e = pmap->pm_top[j];
+ if ((l1e & PTE_V) == 0)
+ continue;
+ pa1 = PTE_TO_PHYS(l1e);
+ m1 = PHYS_TO_VM_PAGE(pa1);
+ l2 = (pd_entry_t *)PHYS_TO_DMAP(pa1);
+
+ for (k = 0; k < Ln_ENTRIES; k++) {
+ l2e = l2[k];
+ if ((l2e & PTE_V) == 0)
+ continue;
+ pa = PTE_TO_PHYS(l2e);
+ m = PHYS_TO_VM_PAGE(pa);
+ l3 = (pt_entry_t *)PHYS_TO_DMAP(pa);
+
+ for (l = 0; l < Ln_ENTRIES; l++) {
+ l3e = l3[l];
+ if ((l3e & PTE_V) == 0)
+ continue;
+ panic("%s: l3e found (idx %d %d %d)",
+ __func__, j, k, l);
+ }
+
+ vm_page_unwire_noq(m1);
+ vm_page_unwire_noq(m);
+ pmap_resident_count_dec(pmap, 1);
+ vm_page_free(m);
+ pmap_clear(&l2[k]);
+ }
+
+ pmap_resident_count_dec(pmap, 1);
+ vm_page_free(m1);
+ pmap_clear(&pmap->pm_top[j]);
+ }
+
+ KASSERT(pmap->sp_resident_count == 0,
+ ("Invalid resident count %jd", pmap->sp_resident_count));
+
+ PMAP_UNLOCK(pmap);
+}
+
+void
+iommu_pmap_remove_pages(struct riscv_iommu_pmap *pmap)
+{
+
+ switch (pmap->pm_mode) {
+ case PMAP_MODE_SV39:
+ iommu_pmap_remove_pages_sv39(pmap);
+ break;
+ case PMAP_MODE_SV48:
+ iommu_pmap_remove_pages_sv48(pmap);
+ break;
+ default:
+ panic("Unknown virtual memory system");
+ }
+}
diff --git a/sys/riscv/iommu/iommu_pmap.h b/sys/riscv/iommu/iommu_pmap.h
new file mode 100644
index 000000000000..25347e239119
--- /dev/null
+++ b/sys/riscv/iommu/iommu_pmap.h
@@ -0,0 +1,49 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2026 Ruslan Bukin <br@bsdpad.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _RISCV_IOMMU_IOMMU_PMAP_H_
+#define _RISCV_IOMMU_IOMMU_PMAP_H_
+
+struct riscv_iommu_pmap {
+ pd_entry_t *pm_top;
+ enum pmap_mode pm_mode;
+ uint64_t pm_satp;
+ struct mtx pm_mtx;
+#ifdef INVARIANTS
+ long sp_resident_count;
+#endif
+};
+
+int iommu_pmap_enter(struct riscv_iommu_pmap *pmap, vm_offset_t va,
+ vm_paddr_t pa, vm_prot_t prot, u_int flags);
+int iommu_pmap_remove(struct riscv_iommu_pmap *pmap, vm_offset_t va);
+void iommu_pmap_remove_pages(struct riscv_iommu_pmap *pmap);
+int iommu_pmap_pinit(struct riscv_iommu_pmap *pmap, enum pmap_mode pm_mode);
+void iommu_pmap_release(struct riscv_iommu_pmap *pmap);
+void iommu_pmap_remove_pages(struct riscv_iommu_pmap *pmap);
+
+#endif /* !_RISCV_IOMMU_IOMMU_PMAP_H_ */
diff --git a/sys/sys/_decls.h b/sys/sys/_decls.h
new file mode 100644
index 000000000000..2ef61671dd70
--- /dev/null
+++ b/sys/sys/_decls.h
@@ -0,0 +1,46 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Berkeley Software Design, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _SYS__DECLS_H_
+#define _SYS__DECLS_H_
+
+#if defined(__cplusplus)
+#define __BEGIN_DECLS extern "C" {
+#define __END_DECLS }
+#else
+#define __BEGIN_DECLS
+#define __END_DECLS
+#endif
+
+#endif
diff --git a/sys/sys/_types.h b/sys/sys/_types.h
index a2ee83a862da..bc438c17c8c0 100644
--- a/sys/sys/_types.h
+++ b/sys/sys/_types.h
@@ -40,18 +40,23 @@
*/
typedef signed char __int8_t;
typedef unsigned char __uint8_t;
+#define __SIZEOF_INT8_T __SIZEOF_CHAR__
typedef short __int16_t;
typedef unsigned short __uint16_t;
+#define __SIZEOF_INT16_T __SIZEOF_SHORT__
typedef int __int32_t;
typedef unsigned int __uint32_t;
+#define __SIZEOF_INT32_T __SIZEOF_INT__
#if __SIZEOF_LONG__ == 8
typedef long __int64_t;
typedef unsigned long __uint64_t;
+#define __SIZEOF_INT64_T __SIZEOF_LONG__
#elif __SIZEOF_LONG__ == 4
__extension__
typedef long long __int64_t;
__extension__
typedef unsigned long long __uint64_t;
+#define __SIZEOF_INT64_T __SIZEOF_LONG_LONG__
#else
#error unsupported long size
#endif
diff --git a/sys/sys/abi_types.h b/sys/sys/abi_types.h
index 44d1bd733bbd..ddacd08ff011 100644
--- a/sys/sys/abi_types.h
+++ b/sys/sys/abi_types.h
@@ -27,8 +27,10 @@ typedef struct {
#if defined(__amd64__) || defined(__i386__)
typedef __int32_t time32_t;
+#define __SIZEOF_TIME32_T __SIZEOF_INT32_T
#else
typedef __int64_t time32_t;
+#define __SIZEOF_TIME32_T __SIZEOF_INT64_T
#endif
#define __HAVE_TIME32_T
diff --git a/sys/sys/cdefs.h b/sys/sys/cdefs.h
index a08c50c8439a..d0a34f1bdfc0 100644
--- a/sys/sys/cdefs.h
+++ b/sys/sys/cdefs.h
@@ -61,13 +61,7 @@
#define __has_builtin(x) 0
#endif
-#if defined(__cplusplus)
-#define __BEGIN_DECLS extern "C" {
-#define __END_DECLS }
-#else
-#define __BEGIN_DECLS
-#define __END_DECLS
-#endif
+#include <sys/_decls.h>
/*
* This code has been put in place to help reduce the addition of
diff --git a/sys/sys/disk/gpt.h b/sys/sys/disk/gpt.h
index 426ae835c0c1..65b00f5de733 100644
--- a/sys/sys/disk/gpt.h
+++ b/sys/sys/disk/gpt.h
@@ -261,6 +261,8 @@ CTASSERT(sizeof(struct gpt_ent) == 128);
#define GPT_ENT_TYPE_U_BOOT_ENV \
{0x3de21764,0x95bd,0x54bd,0xa5,0xc3,{0x4a,0xbe,0x78,0x6f,0x38,0xa8}}
+#define GPT_ENT_TYPE_XBOOTLDR \
+ {0xbc13c2ff,0x59e6,0x4262,0xa3,0x52,{0xb2,0x75,0xfd,0x6f,0x71,0x72}}
/*
* Boot partition used by GRUB 2.
diff --git a/sys/sys/fcntl.h b/sys/sys/fcntl.h
index 0b13241f0ee3..80cbca4ea753 100644
--- a/sys/sys/fcntl.h
+++ b/sys/sys/fcntl.h
@@ -142,6 +142,13 @@ typedef __pid_t pid_t;
#define O_EMPTY_PATH 0x02000000
#define O_NAMEDATTR 0x04000000 /* NFSv4 named attributes */
#define O_XATTR O_NAMEDATTR /* Solaris compatibility */
+
+/*
+ * Emulate MacOSX compatibility flag without consuming a flags bit.
+ * It is not fully correct since reads over regular files opened with
+ * this definition fail.
+ */
+#define O_SYMLINK (O_PATH | O_NOFOLLOW)
#endif
#if __POSIX_VISIBLE >= 202405
diff --git a/sys/sys/malloc.h b/sys/sys/malloc.h
index 9b281da4b4d4..68dffb395534 100644
--- a/sys/sys/malloc.h
+++ b/sys/sys/malloc.h
@@ -61,6 +61,7 @@
#define M_EXEC 0x4000 /* allocate executable space */
#define M_NEXTFIT 0x8000 /* only for vmem, follow cursor */
#define M_NEVERFREED 0x10000 /* chunk will never get freed */
+#define M_UNPROTECTED 0x20000 /* alloc out of unprotected memory */
#define M_VERSION 2024073001
diff --git a/sys/sys/mount.h b/sys/sys/mount.h
index 1ca492929813..d6696bba0a4f 100644
--- a/sys/sys/mount.h
+++ b/sys/sys/mount.h
@@ -36,8 +36,10 @@
#include <sys/ucred.h>
#include <sys/queue.h>
#ifdef _KERNEL
+#include <sys/systm.h>
#include <sys/lock.h>
#include <sys/lockmgr.h>
+#include <sys/proc.h>
#include <sys/tslog.h>
#include <sys/_mutex.h>
#include <sys/_sx.h>
@@ -851,114 +853,134 @@ struct vfsops {
vfs_statfs_t __vfs_statfs;
-#define VFS_MOUNT(MP) ({ \
- int _rc; \
- \
- TSRAW(curthread, TS_ENTER, "VFS_MOUNT", (MP)->mnt_vfc->vfc_name);\
- _rc = (*(MP)->mnt_op->vfs_mount)(MP); \
- TSRAW(curthread, TS_EXIT, "VFS_MOUNT", (MP)->mnt_vfc->vfc_name);\
- _rc; })
+static inline int
+VFS_MOUNT(struct mount *mp)
+{
+ int rc;
-#define VFS_UNMOUNT(MP, FORCE) ({ \
- int _rc; \
- \
- _rc = (*(MP)->mnt_op->vfs_unmount)(MP, FORCE); \
- _rc; })
+ TSRAW(curthread, TS_ENTER, "VFS_MOUNT", mp->mnt_vfc->vfc_name);
+ rc = mp->mnt_op->vfs_mount(mp);
+ TSRAW(curthread, TS_EXIT, "VFS_MOUNT", mp->mnt_vfc->vfc_name);
+ return (rc);
+}
-#define VFS_ROOT(MP, FLAGS, VPP) ({ \
- int _rc; \
- \
- _rc = (*(MP)->mnt_op->vfs_root)(MP, FLAGS, VPP); \
- _rc; })
+static inline int
+VFS_UNMOUNT(struct mount *mp, int force)
+{
+ return (mp->mnt_op->vfs_unmount(mp, force));
+}
-#define VFS_CACHEDROOT(MP, FLAGS, VPP) ({ \
- int _rc; \
- \
- _rc = (*(MP)->mnt_op->vfs_cachedroot)(MP, FLAGS, VPP); \
- _rc; })
+static inline int
+VFS_ROOT(struct mount *mp, int flags, struct vnode **vpp)
+{
+ return (mp->mnt_op->vfs_root(mp, flags, vpp));
+}
-#define VFS_QUOTACTL(MP, C, U, A, MP_BUSY) ({ \
- int _rc; \
- \
- _rc = (*(MP)->mnt_op->vfs_quotactl)(MP, C, U, A, MP_BUSY); \
- _rc; })
+static inline int
+VFS_CACHEDROOT(struct mount *mp, int flags, struct vnode **vpp)
+{
+ return (mp->mnt_op->vfs_cachedroot(mp, flags, vpp));
+}
-#define VFS_STATFS(MP, SBP) ({ \
- int _rc; \
- \
- _rc = __vfs_statfs((MP), (SBP)); \
- _rc; })
+static inline int
+VFS_QUOTACTL(struct mount *mp, int cmds, uid_t uid, void *arg, bool *mp_busy)
+{
+ return (mp->mnt_op->vfs_quotactl(mp, cmds, uid, arg, mp_busy));
+}
-#define VFS_SYNC(MP, WAIT) ({ \
- int _rc; \
- \
- _rc = (*(MP)->mnt_op->vfs_sync)(MP, WAIT); \
- _rc; })
+static inline int
+VFS_STATFS(struct mount *mp, struct statfs *sbp)
+{
+ return (__vfs_statfs(mp, sbp));
+}
-#define VFS_VGET(MP, INO, FLAGS, VPP) ({ \
- int _rc; \
- \
- _rc = (*(MP)->mnt_op->vfs_vget)(MP, INO, FLAGS, VPP); \
- _rc; })
+static inline int
+VFS_SYNC(struct mount *mp, int waitfor)
+{
+ return (mp->mnt_op->vfs_sync(mp, waitfor));
+}
-#define VFS_FHTOVP(MP, FIDP, FLAGS, VPP) ({ \
- int _rc; \
- \
- _rc = (*(MP)->mnt_op->vfs_fhtovp)(MP, FIDP, FLAGS, VPP); \
- _rc; })
+static inline int
+VFS_VGET(struct mount *mp, ino_t ino, int flags, struct vnode **vpp)
+{
+ return (mp->mnt_op->vfs_vget(mp, ino, flags, vpp));
+}
-#define VFS_CHECKEXP(MP, NAM, EXFLG, CRED, NUMSEC, SEC) ({ \
- int _rc; \
- \
- _rc = (*(MP)->mnt_op->vfs_checkexp)(MP, NAM, EXFLG, CRED, NUMSEC,\
- SEC); \
- _rc; })
+static inline int
+VFS_FHTOVP(struct mount *mp, struct fid *fidp, int flags, struct vnode **vpp)
+{
+ return (mp->mnt_op->vfs_fhtovp(mp, fidp, flags, vpp));
+}
-#define VFS_EXTATTRCTL(MP, C, FN, NS, N) ({ \
- int _rc; \
- \
- _rc = (*(MP)->mnt_op->vfs_extattrctl)(MP, C, FN, NS, N); \
- _rc; })
+static inline int
+VFS_CHECKEXP(struct mount *mp, struct sockaddr *nam, uint64_t *extflagsp,
+ struct ucred **credanonp, int *numsecflavors, int *secflavors)
+{
+ return (mp->mnt_op->vfs_checkexp(mp, nam, extflagsp, credanonp,
+ numsecflavors, secflavors));
+}
-#define VFS_SYSCTL(MP, OP, REQ) ({ \
- int _rc; \
- \
- _rc = (*(MP)->mnt_op->vfs_sysctl)(MP, OP, REQ); \
- _rc; })
+static inline int
+VFS_EXTATTRCTL(struct mount *mp, int cmd, struct vnode *filename_vp,
+ int attrnamespace, const char *attrname)
+{
+ return (mp->mnt_op->vfs_extattrctl(mp, cmd, filename_vp,
+ attrnamespace, attrname));
+}
-#define VFS_SUSP_CLEAN(MP) do { \
- if (*(MP)->mnt_op->vfs_susp_clean != NULL) { \
- (*(MP)->mnt_op->vfs_susp_clean)(MP); \
- } \
-} while (0)
+static inline int
+VFS_SYSCTL(struct mount *mp, fsctlop_t op, struct sysctl_req *req)
+{
+ return (mp->mnt_op->vfs_sysctl(mp, op, req));
+}
-#define VFS_RECLAIM_LOWERVP(MP, VP) do { \
- if (*(MP)->mnt_op->vfs_reclaim_lowervp != NULL) { \
- (*(MP)->mnt_op->vfs_reclaim_lowervp)((MP), (VP)); \
- } \
-} while (0)
+static inline void
+VFS_SUSP_CLEAN(struct mount *mp)
+{
+ if (mp->mnt_op->vfs_susp_clean != NULL)
+ mp->mnt_op->vfs_susp_clean(mp);
+}
-#define VFS_UNLINK_LOWERVP(MP, VP) do { \
- if (*(MP)->mnt_op->vfs_unlink_lowervp != NULL) { \
- (*(MP)->mnt_op->vfs_unlink_lowervp)((MP), (VP)); \
- } \
-} while (0)
+static inline void
+VFS_RECLAIM_LOWERVP(struct mount *mp, struct vnode *vp)
+{
+ if (mp->mnt_op->vfs_reclaim_lowervp != NULL)
+ mp->mnt_op->vfs_reclaim_lowervp(mp, vp);
+}
-#define VFS_PURGE(MP) do { \
- if (*(MP)->mnt_op->vfs_purge != NULL) { \
- (*(MP)->mnt_op->vfs_purge)(MP); \
- } \
-} while (0)
+static inline void
+VFS_UNLINK_LOWERVP(struct mount *mp, struct vnode *vp)
+{
+ if (mp->mnt_op->vfs_unlink_lowervp != NULL)
+ mp->mnt_op->vfs_unlink_lowervp(mp, vp);
+}
-#define VFS_KNOTE_LOCKED(vp, hint) do \
-{ \
- VN_KNOTE((vp), (hint), KNF_LISTLOCKED); \
-} while (0)
+static inline void
+VFS_PURGE(struct mount *mp)
+{
+ if (mp->mnt_op->vfs_purge != NULL)
+ mp->mnt_op->vfs_purge(mp);
+}
-#define VFS_KNOTE_UNLOCKED(vp, hint) do \
-{ \
- VN_KNOTE((vp), (hint), 0); \
-} while (0)
+#include <sys/vnode.h>
+
+static inline void
+VFS_KNOTE_LOCKED(struct vnode *vp, int hint)
+{
+ if ((vn_irflag_read(vp) & VIRF_KNOTE) != 0) {
+ KNOTE_LOCKED(&vp->v_pollinfo->vpi_selinfo.si_note,
+ hint);
+ }
+}
+
+static inline void
+VFS_KNOTE_UNLOCKED(struct vnode *vp, int hint)
+{
+ if ((vn_irflag_read(vp) & VIRF_KNOTE) != 0) {
+ KNOTE_UNLOCKED(&vp->v_pollinfo->vpi_selinfo.si_note,
+ hint);
+ }
+}
#include <sys/module.h>
@@ -1137,47 +1159,64 @@ void resume_all_fs(void);
*/
#define vfs_mount_pcpu(mp) zpcpu_get(mp->mnt_pcpu)
#define vfs_mount_pcpu_remote(mp, cpu) zpcpu_get_cpu(mp->mnt_pcpu, cpu)
+static void vfs_op_thread_exit_crit(struct mount *mp, struct mount_pcpu *mpcpu);
-#define vfs_op_thread_entered(mp) ({ \
- MPASS(curthread->td_critnest > 0); \
- struct mount_pcpu *_mpcpu = vfs_mount_pcpu(mp); \
- _mpcpu->mntp_thread_in_ops == 1; \
-})
+static inline bool
+vfs_op_thread_entered(struct mount *mp)
+{
+ struct mount_pcpu *mpcpu = vfs_mount_pcpu(mp);
-#define vfs_op_thread_enter_crit(mp, _mpcpu) ({ \
- bool _retval_crit = true; \
- MPASS(curthread->td_critnest > 0); \
- _mpcpu = vfs_mount_pcpu(mp); \
- MPASS(mpcpu->mntp_thread_in_ops == 0); \
- _mpcpu->mntp_thread_in_ops = 1; \
- atomic_interrupt_fence(); \
- if (__predict_false(mp->mnt_vfs_ops > 0)) { \
- vfs_op_thread_exit_crit(mp, _mpcpu); \
- _retval_crit = false; \
- } \
- _retval_crit; \
-})
+ MPASS(curthread->td_critnest > 0);
+ return (mpcpu->mntp_thread_in_ops == 1);
+}
-#define vfs_op_thread_enter(mp, _mpcpu) ({ \
- bool _retval; \
- critical_enter(); \
- _retval = vfs_op_thread_enter_crit(mp, _mpcpu); \
- if (__predict_false(!_retval)) \
- critical_exit(); \
- _retval; \
-})
+static inline bool
+vfs_op_thread_enter_crit(struct mount *mp, struct mount_pcpu **mpcpup)
+{
+ struct mount_pcpu *mpcpu;
+ bool retval_crit = true;
-#define vfs_op_thread_exit_crit(mp, _mpcpu) do { \
- MPASS(_mpcpu == vfs_mount_pcpu(mp)); \
- MPASS(_mpcpu->mntp_thread_in_ops == 1); \
- atomic_interrupt_fence(); \
- _mpcpu->mntp_thread_in_ops = 0; \
-} while (0)
+ MPASS(curthread->td_critnest > 0);
+ mpcpu = vfs_mount_pcpu(mp);
+ MPASS(mpcpu->mntp_thread_in_ops == 0);
+ mpcpu->mntp_thread_in_ops = 1;
+ atomic_interrupt_fence();
+ if (__predict_false(mp->mnt_vfs_ops > 0)) {
+ vfs_op_thread_exit_crit(mp, mpcpu);
+ retval_crit = false;
+ }
+ *mpcpup = mpcpu;
+ return (retval_crit);
+}
-#define vfs_op_thread_exit(mp, _mpcpu) do { \
- vfs_op_thread_exit_crit(mp, _mpcpu); \
- critical_exit(); \
-} while (0)
+static inline bool
+vfs_op_thread_enter(struct mount *mp, struct mount_pcpu **mpcpup)
+{
+ bool retval;
+
+ critical_enter();
+ retval = vfs_op_thread_enter_crit(mp, mpcpup);
+ if (__predict_false(!retval))
+ critical_exit();
+ return (retval);
+}
+
+static inline void
+vfs_op_thread_exit_crit(struct mount *mp, struct mount_pcpu *mpcpu)
+{
+ MPASS(mpcpu == vfs_mount_pcpu(mp));
+ MPASS(mpcpu->mntp_thread_in_ops == 1);
+
+ atomic_interrupt_fence();
+ mpcpu->mntp_thread_in_ops = 0;
+}
+
+static inline void
+vfs_op_thread_exit(struct mount *mp, struct mount_pcpu *mpcpu)
+{
+ vfs_op_thread_exit_crit(mp, mpcpu);
+ critical_exit();
+}
#define vfs_mp_count_add_pcpu(_mpcpu, count, val) do { \
MPASS(_mpcpu->mntp_thread_in_ops == 1); \
diff --git a/sys/sys/physmem.h b/sys/sys/physmem.h
index 1b75dc63dc40..97c3ad9f3154 100644
--- a/sys/sys/physmem.h
+++ b/sys/sys/physmem.h
@@ -54,6 +54,7 @@
void physmem_hardware_region(uint64_t pa, uint64_t sz);
void physmem_exclude_region(vm_paddr_t pa, vm_size_t sz, uint32_t flags);
size_t physmem_avail(vm_paddr_t *avail, size_t maxavail);
+size_t physmem_all(vm_paddr_t *avail, size_t maxavail);
void physmem_init_kernel_globals(void);
void physmem_print_tables(void);
bool physmem_excluded(vm_paddr_t pa, vm_size_t sz);
diff --git a/sys/sys/power.h b/sys/sys/power.h
index d34af0ddb86a..e420717e1aa7 100644
--- a/sys/sys/power.h
+++ b/sys/sys/power.h
@@ -48,28 +48,29 @@
* Sleep state transition requests.
*
* These are high-level sleep states that the system can enter. They map to
- * a specific generic sleep type (enum power_stype).
+ * a specific generic sleep type (enum power_stype), depending on the
+ * kern.power.* sysctls.
*/
-enum power_sstate_transition {
- POWER_SSTATE_TRANSITION_STANDBY,
- POWER_SSTATE_TRANSITION_SUSPEND,
- POWER_SSTATE_TRANSITION_HIBERNATE,
+enum power_transition {
+ POWER_TRANSITION_STANDBY,
+ POWER_TRANSITION_SUSPEND,
+ POWER_TRANSITION_HIBERNATE,
};
/*
* Sleep type.
*
* These are the specific generic methods of entering a sleep state. E.g.
- * POWER_SSTATE_TRANSITION_SUSPEND could be set to enter either suspend-to-RAM
- * (which is S3 on ACPI systems), or suspend-to-idle (S0ix on ACPI systems).
- * This would be done through the kern.power.suspend sysctl.
+ * POWER_TRANSITION_SUSPEND could be set to enter either firmware suspend (which
+ * is suspend-to-RAM or S3 on ACPI systems), or suspend-to-idle (S0ix on ACPI
+ * platforms). This would be done through the kern.power.suspend sysctl.
*/
enum power_stype {
POWER_STYPE_AWAKE,
POWER_STYPE_STANDBY,
- POWER_STYPE_SUSPEND_TO_MEM,
+ POWER_STYPE_FW_SUSPEND,
POWER_STYPE_SUSPEND_TO_IDLE,
- POWER_STYPE_HIBERNATE,
+ POWER_STYPE_FW_HIBERNATE,
POWER_STYPE_POWEROFF,
POWER_STYPE_COUNT,
POWER_STYPE_UNKNOWN,
@@ -78,9 +79,9 @@ enum power_stype {
static const char * const power_stype_names[POWER_STYPE_COUNT] = {
[POWER_STYPE_AWAKE] = "awake",
[POWER_STYPE_STANDBY] = "standby",
- [POWER_STYPE_SUSPEND_TO_MEM] = "s2mem",
- [POWER_STYPE_SUSPEND_TO_IDLE] = "s2idle",
- [POWER_STYPE_HIBERNATE] = "hibernate",
+ [POWER_STYPE_FW_SUSPEND] = "fw_suspend",
+ [POWER_STYPE_SUSPEND_TO_IDLE] = "suspend_to_idle",
+ [POWER_STYPE_FW_HIBERNATE] = "fw_hibernate",
[POWER_STYPE_POWEROFF] = "poweroff",
};
@@ -96,7 +97,7 @@ extern int power_pm_register(u_int _pm_type, power_pm_fn_t _pm_fn,
void *_pm_arg,
bool _pm_supported[static POWER_STYPE_COUNT]);
extern u_int power_pm_get_type(void);
-extern void power_pm_suspend(enum power_sstate_transition _trans);
+extern void power_pm_suspend(enum power_transition _trans);
/*
* System power API.
diff --git a/sys/sys/time.h b/sys/sys/time.h
index 6f18d8bd844d..5255d3bc9c7e 100644
--- a/sys/sys/time.h
+++ b/sys/sys/time.h
@@ -355,7 +355,7 @@ tstosbt(struct timespec _ts)
static __inline sbintime_t
tstosbt_sat(struct timespec _ts)
{
-#ifndef __i386__
+#if __SIZEOF_TIME_T > 4
if (_ts.tv_sec > SBT_MAX >> 32)
return (SBT_MAX);
if (_ts.tv_sec < -(SBT_MAX >> 32) - 1)
@@ -384,7 +384,7 @@ tvtosbt(struct timeval _tv)
static __inline sbintime_t
tvtosbt_sat(struct timeval _tv)
{
-#ifndef __i386__
+#if __SIZEOF_TIME_T > 4
if (_tv.tv_sec > SBT_MAX >> 32)
return (SBT_MAX);
if (_tv.tv_sec < -(SBT_MAX >> 32) - 1)
diff --git a/sys/sys/ucred.h b/sys/sys/ucred.h
index ba241cf9ff3a..4bf48a5e4b87 100644
--- a/sys/sys/ucred.h
+++ b/sys/sys/ucred.h
@@ -193,6 +193,17 @@ struct setcred32 {
uint32_t sc_label; /* struct mac32 [*] */
};
+#ifdef COMPAT_FREEBSD32
+/* 32-bit compatible version of xucred */
+struct xucred32 {
+ u_int cr_version; /* structure layout version */
+ uid_t cr_uid; /* effective user id */
+ short cr_ngroups; /* number of groups (incl. cr_gid). */
+ gid_t cr_groups[XU_NGROUPS]; /* groups */
+ pid_t cr_pid;
+};
+#endif
+
struct thread;
/* Common native and 32-bit compatibility entry point. */
diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h
index 3fd2c770cda1..4fee025a93ea 100644
--- a/sys/sys/vnode.h
+++ b/sys/sys/vnode.h
@@ -221,21 +221,16 @@ _Static_assert(sizeof(struct vnode) <= 448, "vnode size crosses 448 bytes");
#define bo2vnode(bo) __containerof((bo), struct vnode, v_bufobj)
-/* XXX: These are temporary to avoid a source sweep at this time */
#define v_object v_bufobj.bo_object
-/* We don't need to lock the knlist */
-#define VN_KNLIST_EMPTY(vp) ((vp)->v_pollinfo == NULL || \
- KNLIST_EMPTY(&(vp)->v_pollinfo->vpi_selinfo.si_note))
-
-#define VN_KNOTE(vp, b, a) \
- do { \
- if (!VN_KNLIST_EMPTY(vp)) \
- KNOTE(&vp->v_pollinfo->vpi_selinfo.si_note, (b), \
- (a) | KNF_NOKQLOCK); \
- } while (0)
-#define VN_KNOTE_LOCKED(vp, b) VN_KNOTE(vp, b, KNF_LISTLOCKED)
-#define VN_KNOTE_UNLOCKED(vp, b) VN_KNOTE(vp, b, 0)
+#define VN_KNOTE(vp, b, a) do { \
+ if ((vn_irflag_read(vp) & VIRF_KNOTE) != 0) { \
+ KNOTE(&vp->v_pollinfo->vpi_selinfo.si_note, (b), \
+ (a) | KNF_NOKQLOCK); \
+ } \
+} while (0)
+#define VN_KNOTE_LOCKED(vp, b) VN_KNOTE(vp, b, KNF_LISTLOCKED)
+#define VN_KNOTE_UNLOCKED(vp, b) VN_KNOTE(vp, b, 0)
/*
* Vnode flags.
@@ -260,6 +255,7 @@ _Static_assert(sizeof(struct vnode) <= 448, "vnode size crosses 448 bytes");
#define VIRF_INOTIFY 0x0080 /* This vnode is being watched */
#define VIRF_INOTIFY_PARENT 0x0100 /* A parent of this vnode may be being
watched */
+#define VIRF_KNOTE 0x0200 /* Has knlist */
#define VI_UNUSED0 0x0001 /* unused */
#define VI_MOUNT 0x0002 /* Mount in progress */
@@ -1052,7 +1048,7 @@ void vop_rename_fail(struct vop_rename_args *ap);
off_t osize, ooffset, noffset; \
\
osize = ooffset = noffset = 0; \
- if (!VN_KNLIST_EMPTY((ap)->a_vp)) { \
+ if ((vn_irflag_read((ap)->a_vp) & VIRF_KNOTE) != 0) { \
error = VOP_GETATTR((ap)->a_vp, &va, (ap)->a_cred); \
if (error) \
return (error); \
@@ -1063,10 +1059,8 @@ void vop_rename_fail(struct vop_rename_args *ap);
#define vop_write_post(ap, ret) \
noffset = (ap)->a_uio->uio_offset; \
if (noffset > ooffset) { \
- if (!VN_KNLIST_EMPTY((ap)->a_vp)) { \
- VFS_KNOTE_LOCKED((ap)->a_vp, NOTE_WRITE | \
- (noffset > osize ? NOTE_EXTEND : 0)); \
- } \
+ VFS_KNOTE_LOCKED((ap)->a_vp, NOTE_WRITE | \
+ (noffset > osize ? NOTE_EXTEND : 0)); \
INOTIFY((ap)->a_vp, IN_MODIFY); \
}
diff --git a/sys/vm/pmap.h b/sys/vm/pmap.h
index e6dcd47d32f6..868bb787dc98 100644
--- a/sys/vm/pmap.h
+++ b/sys/vm/pmap.h
@@ -104,6 +104,7 @@ extern vm_offset_t kernel_vm_end;
#define PMAP_ENTER_NOSLEEP 0x00000100
#define PMAP_ENTER_WIRED 0x00000200
#define PMAP_ENTER_LARGEPAGE 0x00000400
+#define PMAP_ENTER_UNPROTECTED 0x00000800
#define PMAP_ENTER_RESERVED 0xFF000000
/*
diff --git a/sys/vm/vm_kern.c b/sys/vm/vm_kern.c
index fc5d0de424bd..41ba07373976 100644
--- a/sys/vm/vm_kern.c
+++ b/sys/vm/vm_kern.c
@@ -270,6 +270,7 @@ kmem_alloc_attr_domain(int domain, vm_size_t size, int flags, vm_paddr_t low,
vm_size_t asize;
int pflags;
vm_prot_t prot;
+ u_int pmap_enter_flags;
object = kernel_object;
asize = round_page(size);
@@ -279,6 +280,11 @@ kmem_alloc_attr_domain(int domain, vm_size_t size, int flags, vm_paddr_t low,
offset = addr - VM_MIN_KERNEL_ADDRESS;
pflags = malloc2vm_flags(flags) | VM_ALLOC_WIRED;
prot = (flags & M_EXEC) != 0 ? VM_PROT_ALL : VM_PROT_RW;
+
+ pmap_enter_flags = prot | PMAP_ENTER_WIRED;
+ if ((flags & M_UNPROTECTED) != 0)
+ pmap_enter_flags |= PMAP_ENTER_UNPROTECTED;
+
VM_OBJECT_WLOCK(object);
for (i = 0; i < asize; i += PAGE_SIZE) {
m = kmem_alloc_contig_pages(object, atop(offset + i),
@@ -296,7 +302,7 @@ kmem_alloc_attr_domain(int domain, vm_size_t size, int flags, vm_paddr_t low,
pmap_zero_page(m);
vm_page_valid(m);
pmap_enter(kernel_pmap, addr + i, m, prot,
- prot | PMAP_ENTER_WIRED, 0);
+ pmap_enter_flags, 0);
}
VM_OBJECT_WUNLOCK(object);
kmem_alloc_san(addr, size, asize, flags);
@@ -363,6 +369,7 @@ kmem_alloc_contig_domain(int domain, vm_size_t size, int flags, vm_paddr_t low,
vm_size_t asize;
u_long npages;
int pflags;
+ u_int pmap_enter_flags;
object = kernel_object;
asize = round_page(size);
@@ -385,12 +392,17 @@ kmem_alloc_contig_domain(int domain, vm_size_t size, int flags, vm_paddr_t low,
vm_page_domain(m), domain));
end_m = m + npages;
tmp = addr;
+
+ pmap_enter_flags = VM_PROT_RW | PMAP_ENTER_WIRED;
+ if ((flags & M_UNPROTECTED) != 0)
+ pmap_enter_flags |= PMAP_ENTER_UNPROTECTED;
+
for (; m < end_m; m++) {
if ((flags & M_ZERO) && (m->flags & PG_ZERO) == 0)
pmap_zero_page(m);
vm_page_valid(m);
pmap_enter(kernel_pmap, tmp, m, VM_PROT_RW,
- VM_PROT_RW | PMAP_ENTER_WIRED, 0);
+ pmap_enter_flags, 0);
tmp += PAGE_SIZE;
}
VM_OBJECT_WUNLOCK(object);
@@ -549,6 +561,7 @@ kmem_back_domain(int domain, vm_object_t object, vm_offset_t addr,
vm_page_t m;
vm_prot_t prot;
int pflags;
+ u_int pmap_enter_flags;
KASSERT(object == kernel_object,
("kmem_back_domain: only supports kernel object."));
@@ -560,6 +573,10 @@ kmem_back_domain(int domain, vm_object_t object, vm_offset_t addr,
pflags |= VM_ALLOC_WAITFAIL;
prot = (flags & M_EXEC) != 0 ? VM_PROT_ALL : VM_PROT_RW;
+ pmap_enter_flags = prot | PMAP_ENTER_WIRED;
+ if ((flags & M_UNPROTECTED) != 0)
+ pmap_enter_flags |= PMAP_ENTER_UNPROTECTED;
+
i = 0;
vm_page_iter_init(&pages, object);
VM_OBJECT_WLOCK(object);
@@ -589,7 +606,7 @@ retry:
("kmem_malloc: page %p is managed", m));
vm_page_valid(m);
pmap_enter(kernel_pmap, addr + i, m, prot,
- prot | PMAP_ENTER_WIRED, 0);
+ pmap_enter_flags, 0);
if (__predict_false((prot & VM_PROT_EXECUTE) != 0))
m->oflags |= VPO_KMEM_EXEC;
}
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
index 7ead7d7e6472..94dd7d3a19bc 100644
--- a/sys/vm/vm_map.c
+++ b/sys/vm/vm_map.c
@@ -4761,8 +4761,7 @@ vm_map_growstack(vm_map_t map, vm_offset_t addr, vm_map_entry_t gap_entry)
* debugger or AIO daemon. The reason is that the wrong
* resource limits are applied.
*/
- if (p != initproc && (map != &p->p_vmspace->vm_map ||
- p->p_textvp == NULL))
+ if (p != initproc && (map != &vm->vm_map || p->p_textvp == NULL))
return (KERN_FAILURE);
MPASS(!vm_map_is_system(map));
diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c
index bdea77bfabf0..233292bdd6cb 100644
--- a/sys/vm/vm_page.c
+++ b/sys/vm/vm_page.c
@@ -110,6 +110,10 @@
#include <vm/uma_int.h>
#include <machine/md_var.h>
+#if defined(__aarch64__)
+#include <machine/pmap.h>
+#include <machine/rsi.h>
+#endif
struct vm_domain vm_dom[MAXMEMDOM];
@@ -1290,6 +1294,10 @@ PHYS_TO_VM_PAGE(vm_paddr_t pa)
vm_page_t m;
#ifdef VM_PHYSSEG_SPARSE
+#if defined(__aarch64__)
+ if (in_realm())
+ pa &= ~prot_ns_shared_pa; /* Mask off secure bit */
+#endif
m = vm_phys_paddr_to_vm_page(pa);
if (m == NULL)
m = vm_phys_fictitious_to_vm_page(pa);
diff --git a/sys/x86/cpufreq/hwpstate_amd.c b/sys/x86/cpufreq/hwpstate_amd.c
index 5e075a26a57b..bbc6592579e3 100644
--- a/sys/x86/cpufreq/hwpstate_amd.c
+++ b/sys/x86/cpufreq/hwpstate_amd.c
@@ -745,7 +745,7 @@ hwpstate_settings(device_t dev, struct cf_setting *sets, int *count)
static int
hwpstate_type_cppc(device_t dev, int *type)
{
- *type |= CPUFREQ_TYPE_ABSOLUTE | CPUFREQ_FLAG_INFO_ONLY |
+ *type = CPUFREQ_TYPE_ABSOLUTE | CPUFREQ_FLAG_INFO_ONLY |
CPUFREQ_FLAG_UNCACHED;
return (0);
}
diff --git a/sys/x86/include/_types.h b/sys/x86/include/_types.h
index b33dc0bfc7af..2630af1257c7 100644
--- a/sys/x86/include/_types.h
+++ b/sys/x86/include/_types.h
@@ -71,10 +71,12 @@ typedef __int64_t __int_fast64_t;
typedef __int64_t __register_t;
typedef __int64_t __segsz_t; /* segment size (in pages) */
typedef __int64_t __time_t; /* time()... */
+#define __SIZEOF_TIME_T __SIZEOF_INT64_T
#else
typedef __int32_t __register_t;
typedef __int32_t __segsz_t;
typedef __int32_t __time_t;
+#define __SIZEOF_TIME_T __SIZEOF_INT32_T
#endif
typedef __uint32_t __uint_fast8_t;
typedef __uint32_t __uint_fast16_t;
diff --git a/tests/sys/kern/subr_physmem_test.c b/tests/sys/kern/subr_physmem_test.c
index b810a2016473..31bd30447e3b 100644
--- a/tests/sys/kern/subr_physmem_test.c
+++ b/tests/sys/kern/subr_physmem_test.c
@@ -79,6 +79,12 @@ ATF_TC_BODY(hwregion, tc)
ATF_CHECK_EQ(len, 2);
ATF_CHECK_EQ(avail[0], 2 * PAGE_SIZE);
ATF_CHECK_EQ(avail[1], 7 * PAGE_SIZE);
+
+ /* Check physmem_all */
+ len = physmem_all(avail, nitems(avail));
+ ATF_CHECK_EQ(len, 2);
+ ATF_CHECK_EQ(avail[0], 2 * PAGE_SIZE);
+ ATF_CHECK_EQ(avail[1], 7 * PAGE_SIZE);
}
ATF_TC_WITHOUT_HEAD(hwregion_exclude);
@@ -106,6 +112,27 @@ ATF_TC_BODY(hwregion_exclude, tc)
ATF_CHECK_EQ(avail[1], 3 * PAGE_SIZE);
ATF_CHECK_EQ(avail[2], 6 * PAGE_SIZE);
ATF_CHECK_EQ(avail[3], 7 * PAGE_SIZE);
+
+ /* Check physmem_all */
+ len = physmem_all(avail, 6);
+ ATF_CHECK_EQ(len, 2);
+ ATF_CHECK_EQ(avail[0], 2 * PAGE_SIZE);
+ ATF_CHECK_EQ(avail[1], 7 * PAGE_SIZE);
+
+ /* Check an excluded region out of the included memory works */
+ physmem_exclude_region(7 * PAGE_SIZE, PAGE_SIZE, EXFLAG_NOALLOC);
+ len = physmem_avail(avail, 6);
+ ATF_CHECK_EQ(len, 4);
+ ATF_CHECK_EQ(avail[0], 2 * PAGE_SIZE);
+ ATF_CHECK_EQ(avail[1], 3 * PAGE_SIZE);
+ ATF_CHECK_EQ(avail[2], 6 * PAGE_SIZE);
+ ATF_CHECK_EQ(avail[3], 7 * PAGE_SIZE);
+
+ /* Check physmem_all */
+ len = physmem_all(avail, 6);
+ ATF_CHECK_EQ(len, 2);
+ ATF_CHECK_EQ(avail[0], 2 * PAGE_SIZE);
+ ATF_CHECK_EQ(avail[1], 7 * PAGE_SIZE);
}
ATF_TC_WITHOUT_HEAD(hwregion_unordered);
@@ -125,6 +152,12 @@ ATF_TC_BODY(hwregion_unordered, tc)
ATF_CHECK_EQ(len, 2);
ATF_CHECK_EQ(avail[0], PAGE_SIZE);
ATF_CHECK_EQ(avail[1], 3 * PAGE_SIZE);
+
+ /* Check physmem_all */
+ len = physmem_all(avail, 4);
+ ATF_CHECK_EQ(len, 2);
+ ATF_CHECK_EQ(avail[0], PAGE_SIZE);
+ ATF_CHECK_EQ(avail[1], 3 * PAGE_SIZE);
}
ATF_TP_ADD_TCS(tp)
diff --git a/tests/sys/netpfil/common/pft_ping.py b/tests/sys/netpfil/common/pft_ping.py
index a2a1d9c7f4ec..ada4f8607ab0 100644
--- a/tests/sys/netpfil/common/pft_ping.py
+++ b/tests/sys/netpfil/common/pft_ping.py
@@ -63,6 +63,7 @@ def prepare_ipv6(send_params):
dst_address = send_params.get('dst_address')
hlim = send_params.get('hlim')
tc = send_params.get('tc')
+ fl = send_params.get('fl')
ip6 = sp.IPv6(dst=dst_address)
if src_address:
ip6.src = src_address
@@ -70,6 +71,8 @@ def prepare_ipv6(send_params):
ip6.hlim = hlim
if tc:
ip6.tc = tc
+ if fl:
+ ip6.fl = fl
return ip6
@@ -224,6 +227,7 @@ def check_ipv6(expect_params, packet):
flags = expect_params.get('flags')
hlim = expect_params.get('hlim')
tc = expect_params.get('tc')
+ fl = expect_params.get('fl')
ip6 = packet.getlayer(sp.IPv6)
if not ip6:
LOGGER.debug('Packet is not IPv6!')
@@ -245,6 +249,9 @@ def check_ipv6(expect_params, packet):
if tc and ip6.tc != tc:
LOGGER.debug(f'Wrong TC value {ip6.tc}, expected {tc}')
return False
+ if fl and ip6.fl != fl:
+ LOGGER.debug(f'Wrong Flow Label value {ip6.fl}, expected {fl}')
+ return False
return True
@@ -635,6 +642,8 @@ def parse_args():
help='ICMP Echo Request payload size')
parser_send.add_argument('--send-tc', type=int,
help='IPv6 Traffic Class or IPv4 DiffServ / ToS')
+ parser_send.add_argument('--send-fl', type=int,
+ help='IPv6 Flow label')
parser_send.add_argument('--send-tcpopt-unaligned', action='store_true',
help='Include unaligned TCP options')
parser_send.add_argument('--send-nop', action='store_true',
@@ -652,6 +661,8 @@ def parse_args():
help='TCP sequence number')
parser_expect.add_argument('--expect-tc', type=int,
help='IPv6 Traffic Class or IPv4 DiffServ / ToS')
+ parser_expect.add_argument('--expect-fl', type=int,
+ help='IPv6 Flow Label')
parser.add_argument('-v', '--verbose', action='store_true',
help=('Enable verbose logging. Apart of potentially useful information '
@@ -673,7 +684,7 @@ def main():
send_params = {}
expect_params = {}
for param_name in (
- 'flags', 'hlim', 'length', 'mss', 'seq', 'tc', 'frag_length',
+ 'flags', 'hlim', 'length', 'mss', 'seq', 'tc', 'fl', 'frag_length',
'sport', 'dport',
):
param_arg = vars(args).get(f'send_{param_name}')
diff --git a/tests/sys/netpfil/ipfw/Makefile b/tests/sys/netpfil/ipfw/Makefile
index 52f898050267..0be870945891 100644
--- a/tests/sys/netpfil/ipfw/Makefile
+++ b/tests/sys/netpfil/ipfw/Makefile
@@ -4,6 +4,7 @@ TESTSDIR= ${TESTSBASE}/sys/netpfil/ipfw
ATF_TESTS_SH+= fwd \
divert \
+ ipv6-flow-id \
log \
lookup \
table
diff --git a/tests/sys/netpfil/ipfw/ipv6-flow-id.sh b/tests/sys/netpfil/ipfw/ipv6-flow-id.sh
new file mode 100644
index 000000000000..fd3ef2f6cd81
--- /dev/null
+++ b/tests/sys/netpfil/ipfw/ipv6-flow-id.sh
@@ -0,0 +1,78 @@
+#
+# Copyright (c) 2026 Boris Lytochkin
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+
+common_dir="$(atf_get_srcdir)/../common"
+. ${common_dir}/utils.subr
+
+NC="nc -w 1 -dnN"
+
+setup_network_v6()
+{
+ epair="$1"
+
+ ifconfig ${epair}a inet6 2001:db8:42::1/64 up no_dad -ifdisabled
+
+ vnet_mkjail alcatraz ${epair}b
+
+ ifconfig -j alcatraz ${epair}b inet6 2001:db8:42::2/64 up no_dad -ifdisabled
+
+ jexec alcatraz /usr/sbin/inetd -p /dev/null $(atf_get_srcdir)/lookup_inetd.conf
+
+ # Sanity checks
+ atf_check -s exit:0 -o ignore ping6 -i .1 -c 3 -s 1200 2001:db8:42::2
+ atf_check -o "inline:GOOD 82\n" ${NC} 2001:db8:42::2 82
+}
+
+atf_test_case "ipv6fl" "cleanup"
+
+ipv6fl_head()
+{
+ atf_set descr 'flow-id test'
+ atf_set require.user root
+ atf_set require.progs python3 scapy
+}
+
+ipv6fl_body()
+{
+
+ firewall_init "ipfw"
+
+ epair=$(vnet_mkepair)
+
+ setup_network_v6 ${epair}
+
+ # Check if the firewall is able to match exact IPv6 flow label
+ firewall_config "alcatraz" ipfw ipfw \
+ "ipfw -q add 100 allow ip6 from any to any flow-id 0xbaad" \
+ "ipfw -q add 200 deny ipv6-icmp from any to any icmp6types 128 in"
+
+ # Check Flow Label matches
+ atf_check -s exit:0 ${common_dir}/pft_ping.py \
+ --sendif ${epair}a \
+ --fromaddr 2001:db8:42::1 \
+ --to 2001:db8:42::2 \
+ --send-fl $((0xbaad)) \
+ --replyif ${epair}a
+
+ # Check Flow Label mismatch
+ atf_check -s exit:1 ${common_dir}/pft_ping.py \
+ --sendif ${epair}a \
+ --fromaddr 2001:db8:42::1 \
+ --to 2001:db8:42::2 \
+ --send-fl $((0xf001)) \
+ --replyif ${epair}a
+
+}
+
+ipv6fl_cleanup()
+{
+ firewall_cleanup $1
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case "ipv6fl"
+}
diff --git a/tools/build/Makefile b/tools/build/Makefile
index f0856900b281..d71cc710be87 100644
--- a/tools/build/Makefile
+++ b/tools/build/Makefile
@@ -360,6 +360,7 @@ DISKINCS+= ${SRCTOP}/sys/sys/disk/bsd.h
.if ${.MAKE.OS} == "FreeBSD"
# Needed to build most of the things below, which include sys/cdefs.h either
# directly or transitively
+SYSINCS+= ${SRCTOP}/sys/sys/_decls.h
SYSINCS+= ${SRCTOP}/sys/sys/_visible.h
SYSINCS+= ${SRCTOP}/sys/sys/cdefs.h
.endif
diff --git a/usr.bin/mkimg/gpt.c b/usr.bin/mkimg/gpt.c
index ce817ea10ed2..4471cfa1d4b4 100644
--- a/usr.bin/mkimg/gpt.c
+++ b/usr.bin/mkimg/gpt.c
@@ -52,6 +52,9 @@ static mkimg_uuid_t gpt_uuid_freebsd_zfs = GPT_ENT_TYPE_FREEBSD_ZFS;
static mkimg_uuid_t gpt_uuid_mbr = GPT_ENT_TYPE_MBR;
static mkimg_uuid_t gpt_uuid_ms_basic_data = GPT_ENT_TYPE_MS_BASIC_DATA;
static mkimg_uuid_t gpt_uuid_prep_boot = GPT_ENT_TYPE_PREP_BOOT;
+static mkimg_uuid_t gpt_uuid_hifive_bbl = GPT_ENT_TYPE_HIFIVE_BBL;
+static mkimg_uuid_t gpt_uuid_xbootldr = GPT_ENT_TYPE_XBOOTLDR;
+static mkimg_uuid_t gpt_uuid_hifive_fsbl = GPT_ENT_TYPE_HIFIVE_FSBL;
static struct mkimg_alias gpt_aliases[] = {
{ ALIAS_EFI, ALIAS_PTR2TYPE(&gpt_uuid_efi) },
@@ -65,6 +68,9 @@ static struct mkimg_alias gpt_aliases[] = {
{ ALIAS_MBR, ALIAS_PTR2TYPE(&gpt_uuid_mbr) },
{ ALIAS_NTFS, ALIAS_PTR2TYPE(&gpt_uuid_ms_basic_data) },
{ ALIAS_PPCBOOT, ALIAS_PTR2TYPE(&gpt_uuid_prep_boot) },
+ { ALIAS_HIFIVE_BBL, ALIAS_PTR2TYPE(&gpt_uuid_hifive_bbl) },
+ { ALIAS_XBOOTLDR, ALIAS_PTR2TYPE(&gpt_uuid_xbootldr) },
+ { ALIAS_HIFIVE_FSBL, ALIAS_PTR2TYPE(&gpt_uuid_hifive_fsbl) },
{ ALIAS_NONE, 0 } /* Keep last! */
};
diff --git a/usr.bin/mkimg/scheme.c b/usr.bin/mkimg/scheme.c
index 80ff456a709f..b64cfe8bd007 100644
--- a/usr.bin/mkimg/scheme.c
+++ b/usr.bin/mkimg/scheme.c
@@ -58,6 +58,9 @@ static struct {
{ "mbr", ALIAS_MBR },
{ "ntfs", ALIAS_NTFS },
{ "prepboot", ALIAS_PPCBOOT },
+ { "hifive-bbl", ALIAS_HIFIVE_BBL },
+ { "xbootldr", ALIAS_XBOOTLDR },
+ { "hifive-fsbl", ALIAS_HIFIVE_FSBL },
{ NULL, ALIAS_NONE } /* Keep last! */
};
diff --git a/usr.bin/mkimg/scheme.h b/usr.bin/mkimg/scheme.h
index 1c234b86d66c..7a5e09036ee3 100644
--- a/usr.bin/mkimg/scheme.h
+++ b/usr.bin/mkimg/scheme.h
@@ -47,6 +47,9 @@ enum alias {
ALIAS_MBR,
ALIAS_NTFS,
ALIAS_PPCBOOT,
+ ALIAS_HIFIVE_BBL,
+ ALIAS_XBOOTLDR,
+ ALIAS_HIFIVE_FSBL,
/* end */
ALIAS_COUNT /* Keep last! */
};
diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile
index 3d3a8443a7cf..9e885d5d45c5 100644
--- a/usr.sbin/Makefile
+++ b/usr.sbin/Makefile
@@ -81,6 +81,7 @@ SUBDIR= adduser \
setfib \
setfmac \
setpmac \
+ smart \
smbmsg \
snapinfo \
spi \
diff --git a/usr.sbin/bsdinstall/bsdinstall.8 b/usr.sbin/bsdinstall/bsdinstall.8
index 282b88328e99..a35c8f56ada7 100644
--- a/usr.sbin/bsdinstall/bsdinstall.8
+++ b/usr.sbin/bsdinstall/bsdinstall.8
@@ -29,7 +29,7 @@
.\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd April 20, 2026
+.Dd May 12, 2026
.Dt BSDINSTALL 8
.Os
.Sh NAME
@@ -109,9 +109,12 @@ for more information on this target.
.Pp
The
.Ev DISTRIBUTIONS
-environment variable is set to
-.Dq base.txz kernel.txz
-by default for this target.
+environment variable is unset by default for this target.
+Instead, the
+.Ev COMPONENTS
+environment variable is effectively set to
+.Dq base kernel kernel-dbg
+for this target.
.It Cm keymap
If the current controlling TTY is a
.Xr syscons 4
@@ -321,8 +324,17 @@ overridden when making scripted or customized installers.
The directory to use for temporary files.
Default:
.Dq Pa /tmp
+.It Ev COMPONENTS
+The set of components to install for scripted installations using
+base system packages, e.g.,
+.Dq base lib32 kernel-dbg tests .
+Default: "base kernel-dbg"
.It Ev DISTRIBUTIONS
-The set of distributions to install, e.g., "base.txz kernel.txz ports.txz".
+The set of distributions to install for traditional installations, e.g.,
+.Dq base.txz kernel.txz ports.txz .
+If unset, then
+.Nm
+will install using base system packages.
Default: unset unless noted otherwise in the
.Sx TARGETS
section.
@@ -609,18 +621,18 @@ A typical bsdinstall script, using the default filesystem layout and the UFS
filesystem, looks like this:
.Bd -literal -offset indent
PARTITIONS=DEFAULT
-DISTRIBUTIONS="kernel.txz base.txz"
+COMPONENTS="base debug"
#!/bin/sh
sysrc ifconfig_DEFAULT=DHCP
sysrc sshd_enable=YES
-pkg install puppet
+pkg install -y puppet
.Ed
.Pp
For a scripted installation involving a ZFS pool spanning multiple disks,
the script instead looks like this:
.Bd -literal -offset indent
-DISTRIBUTIONS="kernel.txz base.txz"
+COMPONENTS="base debug"
export ZFSBOOT_VDEV_TYPE=stripe
export ZFSBOOT_DISKS="ada0 ada1"
export nonInteractive="YES"
@@ -628,7 +640,20 @@ export nonInteractive="YES"
#!/bin/sh
echo "ifconfig_DEFAULT=DHCP" >> /etc/rc.conf
echo "sshd_enable=YES" >> /etc/rc.conf
-pkg install puppet
+pkg install -y puppet
+.Ed
+.Pp
+To install using traditional distributions sets instead of packages, set
+.Ev DISTRIBUTIONS
+to the list of distribution sets to install, like this:
+.Bd -literal -offset indent
+PARTITIONS=DEFAULT
+DISTRIBUTIONS="kernel.txz base.txz"
+
+#!/bin/sh
+sysrc ifconfig_DEFAULT=DHCP
+sysrc sshd_enable=YES
+pkg install -y puppet
.Ed
.Pp
On
@@ -653,7 +678,7 @@ arbitrary commands can be run here to extend the installer.
In addition to the variables in
.Sx ENVIRONMENT VARIABLES ,
in particular
-.Ev DISTRIBUTIONS ,
+.Ev COMPONENTS ,
the preamble can contain a variable
.Ev PARTITIONS
which is passed to the
diff --git a/usr.sbin/bsdinstall/scripts/pkgbase.in b/usr.sbin/bsdinstall/scripts/pkgbase.in
index 89ddc244171e..2c7d6bcae904 100755
--- a/usr.sbin/bsdinstall/scripts/pkgbase.in
+++ b/usr.sbin/bsdinstall/scripts/pkgbase.in
@@ -180,7 +180,18 @@ local function select_components(components, options)
}
append_list(bsddialog_args, checklist_items)
- local exit_code, output = bsddialog(bsddialog_args)
+ local exit_code = 0
+ local output = ""
+ if options.non_interactive then
+ local env_components = os.getenv("COMPONENTS")
+ if env_components then
+ output = env_components:gsub(" ", "\n")
+ else
+ output = "base\nkernel-dbg"
+ end
+ else
+ exit_code, output = bsddialog(bsddialog_args)
+ end
-- This should only be possible if bsddialog is killed by a signal
-- or buggy, we disable the cancel option and esc key.
-- If this does happen, there's not much we can do except exit with a
@@ -300,6 +311,8 @@ local function parse_options()
for _, a in ipairs(arg) do
if a == "--jail" then
options.jail = true
+ elseif a == "--non-interactive" then
+ options.non_interactive = true
else
io.stderr:write("Error: unknown option " .. a .. "\n")
os.exit(1)
diff --git a/usr.sbin/bsdinstall/scripts/script b/usr.sbin/bsdinstall/scripts/script
index 21da2ea7c366..93d07c7899c3 100755
--- a/usr.sbin/bsdinstall/scripts/script
+++ b/usr.sbin/bsdinstall/scripts/script
@@ -40,6 +40,7 @@ f_include $BSDCFG_SHARE/variable.subr
# PARTITIONS
# DISTRIBUTIONS
# BSDINSTALL_DISTDIR
+# COMPONENTS
#
# Default name of the ZFS boot-pool
@@ -97,7 +98,6 @@ awk 'BEGIN {pathb=ARGV[2]; ARGV[2]=""} /^#!/{b=1} {
>$TMPDIR/bsdinstall-installscript-preamble
. $TMPDIR/bsdinstall-installscript-preamble
-: ${DISTRIBUTIONS="kernel.txz base.txz"}; export DISTRIBUTIONS
export BSDINSTALL_DISTDIR
# Re-initialize a new log if preamble changed BSDINSTALL_LOG
@@ -118,37 +118,48 @@ else
fi
bsdinstall mount
-# Fetch missing distribution files, if any
-exec 5>&1
-export BSDINSTALL_DISTDIR=$(`dirname $0`/fetchmissingdists 2>&1 1>&5)
-FETCH_RESULT=$?
-exec 5>&-
+if [ -n "$COMPONENTS" -a -n "$DISTRIBUTIONS" ]; then
+ error "Cannot set both COMPONENTS and DISTRIBUTIONS"
+elif [ -z "$DISTRIBUTIONS" ]; then
+ # If COMPONENTS is set, or neither is, install with pkgbase
+ bsdinstall pkgbase --non-interactive
+else
+ # Otherwise, unpack distsets
-[ $FETCH_RESULT -ne 0 ] && error "Could not fetch remote distributions"
+ # Fetch missing distribution files, if any
+ exec 5>&1
+ export BSDINSTALL_DISTDIR=$(`dirname $0`/fetchmissingdists 2>&1 1>&5)
+ FETCH_RESULT=$?
+ exec 5>&-
-# Unpack distributions
-bsdinstall checksum
-if [ -t 0 ]; then
- # If install is a tty, use distextract as normal
- bsdinstall distextract
-else
- # Otherwise, we need to use tar (see https://reviews.freebsd.org/D10736)
- for set in $DISTRIBUTIONS; do
- f_dprintf "Extracting $BSDINSTALL_DISTDIR/$set"
- # XXX: The below fails if any mountpoints are FAT, due to
- # inability to set ctime/mtime on the root of FAT partitions,
- # which is needed to support e.g. EFI system partitions. tar has
- # no option to ignore this (distextract ignores them internally
- # through a hack), and returns 1 on any warning or error,
- # effectively turning all warnings into fatal errors.
- #
- # Work around this in an extremely lame way for the specific
- # case of EFI system partitions only. This *ONLY WORKS* if
- # /boot/efi is empty and does not handle analogous problems on
- # other systems (ARM, PPC64).
- tar -xf "$BSDINSTALL_DISTDIR/$set" -C $BSDINSTALL_CHROOT --exclude boot/efi
- mkdir -p $BSDINSTALL_CHROOT/boot/efi
- done
+ [ $FETCH_RESULT -ne 0 ] && error "Could not fetch remote distributions"
+
+ bsdinstall checksum
+ if [ -t 0 ]; then
+ # If install is a tty, use distextract as normal
+ bsdinstall distextract
+ else
+ # Otherwise, we need to use tar (see
+ # https://reviews.freebsd.org/D10736)
+ for set in $DISTRIBUTIONS; do
+ f_dprintf "Extracting $BSDINSTALL_DISTDIR/$set"
+ # XXX: The below fails if any mountpoints are FAT, due
+ # to inability to set ctime/mtime on the root of FAT
+ # partitions, which is needed to support e.g. EFI
+ # system partitions. tar has no option to ignore this
+ # (distextract ignores them internally through a hack),
+ # and returns 1 on any warning or error, effectively
+ # turning all warnings into fatal errors.
+ #
+ # Work around this in an extremely lame way for the
+ # specific case of EFI system partitions only. This
+ # *ONLY WORKS* if /boot/efi is empty and does not
+ # handle analogous problems on other systems (ARM,
+ # PPC64).
+ tar -xf "$BSDINSTALL_DISTDIR/$set" -C $BSDINSTALL_CHROOT --exclude boot/efi
+ mkdir -p $BSDINSTALL_CHROOT/boot/efi
+ done
+ fi
fi
# Configure bootloader if needed
diff --git a/usr.sbin/smart/Makefile b/usr.sbin/smart/Makefile
new file mode 100644
index 000000000000..924b06d3ebcb
--- /dev/null
+++ b/usr.sbin/smart/Makefile
@@ -0,0 +1,8 @@
+.include <src.opts.mk>
+
+SMARTDIR=${SRCTOP}/contrib/smart
+.PATH: ${SMARTDIR}
+
+PACKAGE= smart
+
+.include "${SMARTDIR}/Makefile"