DF-4795 / mcmsg_demo.c
/* * DF-4794 / DF-4795 logic demonstrator -- NOT a kernel PoC. * * Replays the exact msgbuf arithmetic of e1000_update_mc_addr_list_vf() * (sys/dev/netif/ig_hal/e1000_vf.c:400-437) for the current DragonFly * ordering vs the fixed (upstream FreeBSD) ordering, using the real macro * values from e1000_mbx.h (62, 74, 80, 82). Also reports which bytes of * the 16-word msgbuf remain UNINITIALIZED kernel stack when * mc_addr_count < 30: e1000_write_msg_read_ack() (e1000_vf.c:380-389,436) * hands all E1000_VFMAILBOX_SIZE(16) words to write_posted(), and * e1000_write_mbx_vf() copies all `size` words verbatim into the * E1000_VMBMEM registers the PF (hypervisor) reads (e1000_mbx.c:476-477). * * Deterministic arithmetic only -- no hardware needed, and it claims * nothing beyond what the source ordering proves. */ #include <stdio.h> #include <stdint.h> #include <string.h> #define E1000_VFMAILBOX_SIZE 16 #define E1000_VT_MSGINFO_SHIFT 16 #define E1000_VF_SET_MULTICAST 0x03 #define E1000_VF_SET_MULTICAST_OVERFLOW (0x80u << E1000_VT_MSGINFO_SHIFT) static void emulate(unsigned count, int fixed, uint32_t msgbuf[], int init[]) { unsigned i, n = count; uint16_t *hash_list = (uint16_t *)&msgbuf[1]; memset(msgbuf, 0, sizeof(uint32_t) * E1000_VFMAILBOX_SIZE); memset(init, 0, sizeof(int) * 4 * E1000_VFMAILBOX_SIZE); if (!fixed) { /* current DragonFly (e1000_vf.c:421-427) */ if (n > 30) { msgbuf[0] |= E1000_VF_SET_MULTICAST_OVERFLOW; n = 30; } msgbuf[0] = E1000_VF_SET_MULTICAST; /* kills the flag */ } else { /* fixed (upstream FreeBSD ordering) */ if (n > 30) { msgbuf[0] = E1000_VF_SET_MULTICAST | E1000_VF_SET_MULTICAST_OVERFLOW; n = 30; } else { msgbuf[0] = E1000_VF_SET_MULTICAST; } } msgbuf[0] |= n << E1000_VT_MSGINFO_SHIFT; for (i = 0; i < 4; i++) init[i] = 1; /* hash loop writes hash_list[0..n-1] == msgbuf bytes 4..4+2n-1 */ for (i = 0; i < n; i++) { hash_list[i] = 0x0abc; init[4 + 2 * i] = 1; init[4 + 2 * i + 1] = 1; } } int main(void) { uint32_t msgbuf[E1000_VFMAILBOX_SIZE]; int init[4 * E1000_VFMAILBOX_SIZE]; unsigned counts[] = { 5, 31, 128 }; unsigned c; int uninit_bytes, i, fixed; printf("E1000_VF_SET_MULTICAST_OVERFLOW = 0x%08x\n\n", E1000_VF_SET_MULTICAST_OVERFLOW); for (fixed = 0; fixed <= 1; fixed++) { printf("=== %s ordering ===\n", fixed ? "FIXED (upstream)" : "CURRENT DragonFly"); for (c = 0; c < sizeof(counts) / sizeof(counts[0]); c++) { emulate(counts[c], fixed, msgbuf, init); uninit_bytes = 0; for (i = 0; i < 4 * E1000_VFMAILBOX_SIZE; i++) if (!init[i]) uninit_bytes++; printf(" mc_addr_count=%3u: PF-visible msgbuf[0]=0x%08x " "(OVERFLOW flag %s), uninit stack bytes sent to PF: " "%d of 60\n", counts[c], msgbuf[0], (msgbuf[0] & E1000_VF_SET_MULTICAST_OVERFLOW) ? "SET" : "LOST", uninit_bytes); } } return 0; } |