aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Bowling <kbowling@FreeBSD.org>2026-07-30 10:29:57 +0000
committerKevin Bowling <kbowling@FreeBSD.org>2026-07-30 14:05:59 +0000
commit7cd6d2365b3121743dfd6012e259a3b05b0e7adb (patch)
treeb2f27583d8e12a918ae1681fa1ad4c2155cf524e
parent81efd611d81743fa08d36ee830d4c28e1955badd (diff)
e1000: Correct VF register validation
Pass the VF generation through the CSR accessors so the validator can distinguish the sparse 82576 and I350 register maps. Admit the queue-zero RXCTRL, TXCTRL, TDWBAL, TDWBAH, and VFPSRTYPE registers exposed by both families. 82576 exposes VFMPRC at 0xf3c. I350 erratum 31 makes its corrected 0xf38 address inaccessible to a VF, so reject both I350 spellings while retaining read access on 82576. Sponsored by: BBOX.io
-rw-r--r--sys/dev/e1000/e1000_osdep.h22
-rw-r--r--sys/dev/e1000/if_em.c1
2 files changed, 19 insertions, 4 deletions
diff --git a/sys/dev/e1000/e1000_osdep.h b/sys/dev/e1000/e1000_osdep.h
index c7e938f5c93c..0f6364f9a7b5 100644
--- a/sys/dev/e1000/e1000_osdep.h
+++ b/sys/dev/e1000/e1000_osdep.h
@@ -162,6 +162,7 @@ struct e1000_osdep
device_t dev;
if_ctx_t ctx;
bool vf;
+ bool vf_82576;
};
#ifdef INVARIANTS
@@ -174,7 +175,7 @@ struct e1000_osdep
* support must extend this predicate from the applicable device CSR map.
*/
static __inline bool
-e1000_vf_reg_valid(uint32_t reg, bool write)
+e1000_vf_reg_valid(uint32_t reg, bool write, bool vf_82576)
{
/* VF mailbox memory: 16 dwords beginning at 0x800. */
if (reg >= 0x00800 && reg <= 0x0083c && (reg & 3) == 0)
@@ -191,6 +192,7 @@ e1000_vf_reg_valid(uint32_t reg, bool write)
case 0x02808: /* RDLEN */
case 0x0280c: /* SRRCTL */
case 0x02810: /* RDH */
+ case 0x02814: /* RXCTL */
case 0x02818: /* RDT */
case 0x02828: /* RXDCTL */
return (true);
@@ -202,15 +204,26 @@ e1000_vf_reg_valid(uint32_t reg, bool write)
case 0x03804: /* TDBAH */
case 0x03808: /* TDLEN */
case 0x03810: /* TDH */
+ case 0x03814: /* TXCTL */
case 0x03818: /* TDT */
case 0x03828: /* TXDCTL */
+ case 0x03838: /* TDWBAL */
+ case 0x0383c: /* TDWBAH */
return (true);
}
+ /*
+ * 82576 exposes VFMPRC at 0xf3c. I350 erratum 31 makes
+ * its corrected 0xf38 address inaccessible to a VF.
+ */
+ if (vf_82576 && reg == 0x00f3c)
+ return (!write);
+
switch (reg) {
case 0x00000: /* CTRL */
case 0x000c4: /* Legacy ITR, listed but unused by igb VFs */
case 0x00c40: /* V2PMAILBOX(0) */
+ case 0x00f0c: /* VFPSRTYPE */
case 0x01524: /* EIMS */
case 0x0152c: /* EIAC */
case 0x01530: /* EIAM */
@@ -225,7 +238,6 @@ e1000_vf_reg_valid(uint32_t reg, bool write)
case 0x00f14: /* VFGPTC */
case 0x00f18: /* VFGORC */
case 0x00f34: /* VFGOTC */
- case 0x00f3c: /* VFMPRC */
case 0x00f40: /* VFGPRLBC */
case 0x00f44: /* VFGPTLBC */
case 0x00f48: /* VFGORLBC */
@@ -261,7 +273,8 @@ e1000_rd32(struct e1000_osdep *osdep, uint32_t reg)
("e1000: register offset %#jx too large (max is %#jx)",
(uintmax_t)reg, (uintmax_t)osdep->mem_bus_space_size));
#ifdef INVARIANTS
- KASSERT(!osdep->vf || e1000_vf_reg_valid(reg, false),
+ KASSERT(!osdep->vf ||
+ e1000_vf_reg_valid(reg, false, osdep->vf_82576),
("e1000: invalid VF register read at %#x", reg));
#endif
@@ -278,7 +291,8 @@ e1000_wr32(struct e1000_osdep *osdep, uint32_t reg, uint32_t value)
("e1000: register offset %#jx too large (max is %#jx)",
(uintmax_t)reg, (uintmax_t)osdep->mem_bus_space_size));
#ifdef INVARIANTS
- KASSERT(!osdep->vf || e1000_vf_reg_valid(reg, true),
+ KASSERT(!osdep->vf ||
+ e1000_vf_reg_valid(reg, true, osdep->vf_82576),
("e1000: invalid VF register write at %#x", reg));
#endif
diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c
index 2269f3014abb..db84004643f2 100644
--- a/sys/dev/e1000/if_em.c
+++ b/sys/dev/e1000/if_em.c
@@ -1254,6 +1254,7 @@ em_if_attach_pre(if_ctx_t ctx)
/* Determine hardware and mac info */
em_identify_hardware(ctx);
+ sc->osdep.vf_82576 = sc->hw.mac.type == e1000_vfadapt;
/* VF sysctls are deferred until attach-post confirms MSI-X. */
ctx_list = device_get_sysctl_ctx(dev);