Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 30 Jul 2026 14:06:06 +0000
From:      Kevin Bowling <kbowling@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 7cd6d2365b31 - main - e1000: Correct VF register validation
Message-ID:  <6a6b5a4e.1dc2e.6510fc08@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch main has been updated by kbowling:

URL: https://cgit.FreeBSD.org/src/commit/?id=7cd6d2365b3121743dfd6012e259a3b05b0e7adb

commit 7cd6d2365b3121743dfd6012e259a3b05b0e7adb
Author:     Kevin Bowling <kbowling@FreeBSD.org>
AuthorDate: 2026-07-30 10:29:57 +0000
Commit:     Kevin Bowling <kbowling@FreeBSD.org>
CommitDate: 2026-07-30 14:05:59 +0000

    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
---
 sys/dev/e1000/e1000_osdep.h | 22 ++++++++++++++++++----
 sys/dev/e1000/if_em.c       |  1 +
 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);


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6a6b5a4e.1dc2e.6510fc08>