aq(4): correct Atlantic 2 register access
Four Atlantic 2 register-access corrections found in bring-up.
B0 aggregate octet counters: the B0 firmware statistics interface reports
only aggregate rx/tx good octets, not the per-cast breakdown A0 and
Atlantic 1 provide, so every octet sysctl read a permanent zero while
frame counters advanced. Populate the aggregate octet fields from the B0
buffer; aq_update_hw_stats() accumulates them directly when the per-cast
octets are absent.
Drop the duplicate attach-time MCP reboot: aq_hw_mpi_create() already
reboots the A2 firmware to read its version and caps, then aq_hw_reset()
immediately rebooted it again -- a full MCP restart plus several
transaction-id-bracketed window reads, adding attach latency and a
duplicate banner. Give aq_hw_reset() a reboot flag and pass reboot=false
for A2 at attach; the load-bearing down/stop reboot (which resyncs A2 RX
DMA across ifconfig down/up) keeps reboot=true.
[14 lines not shown]
aq(4): program the Atlantic 2 multiqueue datapath
Wire up the Atlantic 2 receive datapath: the action-resolver table (ART),
multiqueue RSS, QoS, and interrupt moderation.
RX action-resolver table: Atlantic 2 replaces Atlantic 1's discrete RX
filter registers with an ART -- hardware computes a per-packet
classification tag, then walks {tag, mask, action} rows to drop, assign a
queue, or assign a TC. aq_hw_art_filter_set() installs one row under the
ART semaphore; aq_hw_init_rx_path() enables the resolver, tags L2
unicast/broadcast, installs the unicast/all-multicast and VLAN drop rows,
and assigns every 802.1p priority to TC 0 (mirroring the Atlantic 1
user-priority map, since our RX side is a single 8-ring group in TC 0).
Tag every enabled VLAN filter in the per-filter resolver-tag field -- a
register the BSD ports never write -- because the VLAN drop row matches
resolver tag 0, so without it all tagged receive was dead under VLAN
filtering. Promiscuous mode disables the drop rows rather than toggling
the Atlantic 1 promiscuous bits; all ART callers surface a semaphore
timeout consistently. The Atlantic 1 RX_TCP_RSS_HASH and TPO2
[26 lines not shown]
aq(4): add Atlantic 2 (AQC113) device support
Add support for the Marvell Atlantic 2 (AQC113/114/115/116) controllers,
a new chip generation that is not register-compatible with the Atlantic 1
parts aq(4) supports today. Adapted from the OpenBSD/NetBSD if_aq driver.
Register and device definitions (aq2_hw.h): the firmware handshake
(MIF_BOOT / MCP_HOST_REQ_INT / MIF_HOST_FINISHED), the 0x12000/0x13000
firmware interface windows, and the action-resolver table (ART) that
replaces Atlantic 1's discrete RX filters, plus the Atlantic 2 PCI device
ids and the aq_is_atlantic2() helper. Reserve a chip-feature bit
(AQ_HW_CHIP_ATLANTIC2) and add the aq_hw fields the firmware fills at boot
(ART base index, statistics interface version A0/B0). The per-VLAN-filter
resolver-tag field comes from the Linux driver; the BSD sources never
write it.
Firmware operations (aq_fwa2.c): Atlantic 2 talks to the management CPU
through the 0x12000/0x13000 register windows plus the boot handshake,
rather than Atlantic 1's mailbox in shared RAM. Implement that as a third
[31 lines not shown]
aq(4): remove dead code and tidy macros, diagnostics, and naming
Non-functional cleanup, with two diagnostic corrections.
Dead code: delete leftover commented-out AQ_DBG_ENTER/EXIT/PRINT calls
(aq_hw.c, aq_fw2x.c, aq_irq.c, aq_main.c), a commented-out aq_nic_cfg
local, the stale old-signature parameter blocks between the ring-init
declarations and their bodies (aq_ring.c), a trailing note on a live
statement, and the unused DumpHex() vendor debug helper (no callers; its
body only compiled under AQ_CFG_DEBUG_LVL > 3).
Register-write macros: parenthesize AQ_WRITE_REG_BIT's msk/shift/value
arguments so a compound argument cannot mis-bind, give AQ_HW_FLUSH() an
explicit hw parameter instead of capturing it from caller scope, and drop
the duplicate lowercase aq_hw_write_reg[_bit] aliases (converting the 43
call sites to the uppercase spelling) so there is a single form.
Diagnostics: the aq_log* family expanded through the base log macro, which
ignored its level and printed unconditionally, while the error traces
[29 lines not shown]
aq(4): harden the interrupt and MAC-statistics paths
Firmware-statistics accounting and interrupt-routing fixes.
Stats delta underflow: guard the MAC statistics delta accumulation
against counter wrap or a firmware counter reset, so a snapshot smaller
than the previous one does not underflow into a huge spurious delta.
Skip stats on a failed read: aq_update_hw_stats() ignored
aq_hw_mpi_read_stats()'s return and committed the on-stack mbox into
last_stats unconditionally. On a failed read that snapshot is garbage or
zero and poisons the delta baseline (a zeroed snapshot wipes last_stats,
so the next good read double-counts). Check the return and skip the
accumulation and the last_stats commit on failure.
Mailbox/stats separation: struct aq_hw_stats served both as the raw fw1x
MCP mailbox layout and as the driver's canonical stats snapshot, so any
field added to it would silently shift the fw1x mailbox read. Give the
fw1x mailbox its own raw layout in struct aq_hw_fw_mbox and let
[23 lines not shown]
aq(4): harden the attach, detach, and reset error paths
Correct several attach/detach/reset paths that either swallowed failures
or acted on undefined state.
MSI-X attach-failure double-free: aq_if_msix_intr_assign() freed the
per-RX-ring interrupts in its failure path and then returned an error, so
iflib's IFDI_DETACH freed the same irq structures again --
bus_teardown_intr() on a dangling tag and bus_release_resource() on an
already-released IRQ, panicking a box that should have simply failed to
attach. Let iflib own the teardown; drop the failure-path loop and the
now-dead index bookkeeping.
Detach loop bound: aq_if_detach() freed the per-ring interrupts looping
to isc_nrxqsets while indexing rx_rings[], which is sized by
rx_rings_count; index by rx_rings_count to match every other RX-ring
loop.
AQ_HW_WAIT_FOR final poll: the macro derived its result from the loop
[31 lines not shown]
aq(4): honor the kernel RSS policy and add a TX traffic-class helper
Align RX steering with the kernel RSS framework and factor out the
active-traffic-class count.
RSS key and indirection table: on an options RSS kernel the stack owns a
canonical hash key and a hash-to-bucket indirection table binding each
bucket to a CPU. aq programmed a random arc4rand() key and a plain
i % rss_qs table, so the hash it stamped in iri_flowid and the queue it
steered a flow to did not match the CPU the stack chose -- defeating RSS
affinity. Under #ifdef RSS take the key from rss_getkey() and each entry
from rss_get_indirection_to_bucket(), as e1000/ixgbe/ixl do; the non-RSS
build keeps the random key and round-robin table.
RSS hash-type policy: drop the private hw.aq.enable_rss_udp knob (RDTUN,
default on) and add aq_rss_hashconfig(), which under options RSS returns
rss_gethashconfig() and otherwise the same UDP-off default. UDP 4-tuple
hashing scatters a fragmented datagram's pieces across queues because
only the first fragment carries the L4 ports, so it is now off by default
[11 lines not shown]
aq(4): drop errored RX frames instead of resetting the interface
aq_isc_rxd_pkt_get() returned EBADMSG when a receive descriptor's
MAC/receive-error bit (rx_stat bit 0) was set. iflib treats any error
from isc_rxd_pkt_get() as a fatal ring fault and answers with
IFC_DO_RESET -- a full interface reinitialization. A per-frame receive
error is not a ring fault: on a marginal link or cable the Atlantic
delivers errored frames continuously, so each one triggered another
reset and the interface reset-stormed itself into carrying no traffic
instead of merely dropping the bad frames.
The Atlantic delivers errored frames to the host by design (Linux drops
them in software via buff->is_error), and iflib offers no per-frame
error return that isn't a reset. Follow the vmxnet3 model: on a receive
error zero the fragment lengths and return success. iflib then discards
the packet (assemble_segments() excludes zero-length fragments) while
still recycling the descriptors through the refill path -- no reset.
Also drop frames flagged with an RX-DMA fault (rdm_err), not just the
MAC-error bit; and keep iri_len non-zero on that drop path, since iflib
[9 lines not shown]
aq(4): expand and correct offloads, fix VLAN/multicast filtering
Advertise the offloads the hardware already performs, correct the TX
descriptor's L3 family selection, and correct the VLAN and multicast
receive-filter paths.
Offloads: advertise IFCAP_HWCSUM_IPV6 (adding CSUM_IP6_TCP/UDP/TSO to
isc_tx_csum_flags) and IFCAP_VLAN_HWTSO, and enable the RX outer
(S-VLAN) tag parse mode in aq_hw_offload_set().
TX descriptor L3 family: aq_setup_offloads() derived tx_desc_cmd_ipv4
from CSUM_IP|CSUM_TSO, but CSUM_TSO is (CSUM_IP_TSO|CSUM_IP6_TSO) and
tcp_output() sets both bits without regard to address family, so an
IPv6 TSO frame matched on CSUM_IP_TSO and went out with the IPv4
header-checksum command set on a frame that carries no IPv4 header.
The checksum flags cannot distinguish the family; key the bit off
IPI_TX_IPV4 instead, which iflib derives from the parsed ethertype,
as the IPI_TX_INTR test below it already does. Plain IPv6 checksum
offload was unaffected, as CSUM_IP6_TCP alone never matched the mask.
[25 lines not shown]
nullfs: close a race when syncing inotify flags from the lower vnode
After a bypassed VOP, nullfs mirrors the lower vnode's inotify state
onto the upper vnode. The flags were checked with lockless reads
before being updated with the asserting flag set/unset primitives, so
two threads syncing the same vnode concurrently (or a sync racing a
watch being established) could both decide to make the same change;
the loser then trips the "flags already set" assertion on an
INVARIANTS kernel. On other kernels the race is harmless.
Keep the lockless check as the fast path, but re-make the decision
under the vnode interlock before actually changing the flags.
Reproduced in a 4-CPU VM with one thread cycling an inotify watch on
a lower-filesystem file while several threads stat(2) the same file
through a nullfs mount: the unpatched INVARIANTS kernel panics under
this load, the patched kernel runs it to completion.
Fixes: f1f230439fa4 ("vfs: Initial revision of inotify")
[4 lines not shown]
certctl: Enforce 0444 mode on new files
When writing to a file, call fchmod() to ensure the file mode matches
the intended mode, which is 0444. This was already done when replacing
an existing file, but not when creating a new file, which meant if the
process umask was 077, the resulting certificates and bundle would be
unreadable by unprivileged users.
MFC after: 1 week
Reviewed by: des
Differential Revision: https://reviews.freebsd.org/D58304
i386: supply thermal interrupt handler
This fixes a build break for i386.
Reviewed by: kib, olce, Koine Yuusuke <koinec at yahoo.co.jp>
Fixes: 87ba088fa310 ("x86/local_apic.c: Add support for installing a thermal interrupt handler")
Differential Revision: https://reviews.freebsd.org/D58332
dpaa2: Apply if_flags and MAC filters in dpaa2_ni_init()
dpaa2_ni_init() only enabled the DPNI object; it never pushed the
promiscuous/allmulti state or the multicast filter table to the MC
firmware. The SIOCSIFFLAGS handler ignores flag changes that arrive
while the interface is down, yet still latches them into sc->if_flags,
so a promiscuous mode request made before the first up was silently
lost and could never be applied afterwards: the up path runs
dpaa2_ni_init(), which did not read the flags, and every later
SIOCSIFFLAGS compares against the already-latched value and sees no
change.
This is exactly what happens when if_bridge adds a dpni member while
the dpni is still down, e.g. rc.conf's
create_args_bridge0="... addm dpni0"
running at bridge clone time, before ifconfig_dpni0="up" is processed.
bridge_ioctl_add() puts the member into promiscuous mode at addm time;
[18 lines not shown]
vm_phys: Add a sysctl to dump registered fictitious memory ranges
I've wanted this a couple of times in the past. Save the memattr in
the fictitious memory segment structure so that we can report it from
the sysctl handler, and add conversion routines for each platform.
Reviewed by: kib
MFC after: 2 weeks
Differential Revision: https://reviews.freebsd.org/D58283
bhyve: add configurable SMBIOS OEM Strings
Add the option "oemstring" to allow setting the DMI type 11 ("OEM
Strings") SMBIOS structure. These are free-form strings, available for
any purpose, but can be especially useful to pass configuration,
secrets, and credential information into a Linux guest and consumed by
systemd.
MFC after: 1 month
Relnotes: yes
Reviewed by: markj
Differential Revision: https://reviews.freebsd.org/D57516
tcp: Align PRR implementation with RFC 9937
- Early return when no new data is delivered
- Switching from PRR-CRB to PRR-SSRB only when both SND.UNA advances and no further loss is indicated.
- Accounting for sequence ranges SACKed before entering recovery in RecoverFS calculation.
- Force a fast retransmit upon entering recovery when prr_out is 0 AND SndCnt is 0.
- Set cwnd to ssthresh post recovery.
Obtained from: mohnishhemanthkumar_gmail.com
Reviewed by: rscheff, tuexen
Differential Revision: https://reviews.freebsd.org/D56535
MFC after: 3 months
nfs_clstate.c: Fix handling of delegation upgrades
Commit 016570c4463d modified the client to handle
the upgrade of a read delegation to a write delegation,
where the server provides the same delegation stateid
to the client. However, it failed to check if the
delegation structure was currently in use. Without this
patch, if the structure was in use, a use after free
could occur.
This patch handles the "in use" case by copying the
necessary fields into the current/old structure and
free's the new one instead of the old one that is
"in use".
PR: 296224
(cherry picked from commit fe6677e7f440d1aa52de036639efc55047ab9a2b)
nfs_clstate.c: Fix handling of delegation upgrades
Commit 016570c4463d modified the client to handle
the upgrade of a read delegation to a write delegation,
where the server provides the same delegation stateid
to the client. However, it failed to check if the
delegation structure was currently in use. Without this
patch, if the structure was in use, a use after free
could occur.
This patch handles the "in use" case by copying the
necessary fields into the current/old structure and
free's the new one instead of the old one that is
"in use".
PR: 296224
(cherry picked from commit fe6677e7f440d1aa52de036639efc55047ab9a2b)
arm64/vmm: Fix vgic_v3 dropping EOI for disabled IRQs
Now that IRQs can properly be disabled by GICD_ICENABLERn, an EOI for a
disabled IRQ ends up being lost, since we don't assign it to a list
register and don't enable maintenance interrupts for such cases. As a
result, we keep the IRQ active, which stops it from ever being delivered
again (which would be true even if we supported the active and pending
state). Keep disabled but active IRQs around in list registers so we can
see the EOI having taken place in a future sync (noting that since we
already don't create list registers in active and pending state there
are no concerns with causing a disabled IRQ to be delivered).
Fixes: 47e073941f4e ("Import the kernel parts of bhyve/arm64")
MFC after: 1 week