From nobody Mon Aug 10 23:32:07 2026 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4hJrd63mvZz6mBKB for ; Mon, 10 Aug 2026 23:32:10 +0000 (UTC) (envelope-from oliver.pntr@gmail.com) Received: from mail-yw1-x1136.google.com (mail-yw1-x1136.google.com [IPv6:2607:f8b0:4864:20::1136]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "smtp.gmail.com", Issuer "WR4" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4hJrd619Llz41yh for ; Mon, 10 Aug 2026 23:32:10 +0000 (UTC) (envelope-from oliver.pntr@gmail.com) Authentication-Results: mx1.freebsd.org; none Received: by mail-yw1-x1136.google.com with SMTP id 00721157ae682-81ed000b507so20610287b3.0 for ; Mon, 10 Aug 2026 16:32:10 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1786404729; cv=none; d=google.com; s=arc-20260327; b=GgboU2PH1+pFPpa7j77dQRAA3/HKNmWntfUR//7vYG7Z8xekmAaKM23icEeIOpq0CT mYmutRne8YMGbttf1T5oQePS/3nJYnKUvmK9CNhbFuMv56ldAe6xgMfpy+1kHJ+oGlQ5 9I2uM0lqgzZz/5uAas4KL+F3zqVTY5U1GTbA+Ruku9CzwSrNS2htFRUWduqlUcbXAPpQ NyX+7T094PeCJX3jTl6DtMTjFRSVsvbAlBOJNkcbePZzTcLaXtcdJ2nDA/zWMzqkXIvu 7SCCpD+TyUsz/hjGCxfPH5q+XXJ3bzA4pd8EdmXj1GIbe6KTmaLT9s9trTjKO3hRvTFy XcIg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; h=cc:to:subject:message-id:date:from:references:in-reply-to :mime-version:dkim-signature; bh=untlsWKCmUskRJ6IcVNxtDJPP7daDw4oG9bUyYqHSdU=; fh=rnVWJNVsjpK38V9IGarLqMmbUtnYdplpNE0nPXZA1iU=; b=TKCFkYePNYC9YocGG0xFmqbQ/DiJ5GgWxU0fXXXbd/JnjwRolIxgdvncNU10E2GUop M4uYnboUyisfPn8ORBL1/+WwsI1Fpt5nYSF4fvhsy3HSkEIx5kSoM4A23sC1lWuq+HHj M19xIVzxr71g8PPJvpHKZIP64tg+mJoEGjr7wVPNiWHzblNdf5SU3ojtDVYvG31mUhxi v/jGcbT6HfnUjVQSzbtllfaaWPbdVGVVKXHPR4uJCA5YSuSKx5ucp+jxWri0lS2pRsh2 GaD9CSSC8p+O0Ntwt+X5zwlMae8CApE8+mUBQhRqDVByCd/93AKEjL2kfuG/CiGjxNWp ze/Q==; darn=freebsd.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1786404729; x=1787009529; darn=freebsd.org; h=content-type:cc:to:subject:message-id:date:from:references :in-reply-to:mime-version:from:to:cc:subject:date:message-id :reply-to:content-type; bh=untlsWKCmUskRJ6IcVNxtDJPP7daDw4oG9bUyYqHSdU=; b=a7cdnWoszMQJMEQoC0ekUeS3CTzGgKLJrikMvPO7N02nXRcrNTjDX9K5nOn6IO1GSD KjU2LoLIV1TJbTJJzzqmxuZfDO4op7OW5a4G2i5WV1qhZmkUnlvRhQlHJAGTeRkZ5PMH MDYa9lpulS8RuJL4aGPl/RV0UtHfI6e9UAay6iwmixIOT7ejZLC/jrDnPUosMijBBLGw ABY+s7blX126YmuILMMM4uCbH3IblpAeGkGIE67adIgF0C9N3NkRAxWXy8At2+zuKbL4 RQr4uofcCh4t6wZNrK2AP0I2sNDhIf0k78+WCP3KpetFrnqsU451eSFojBPlDRABxQCl 2eHg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786404729; x=1787009529; h=content-type:cc:to:subject:message-id:date:from:references :in-reply-to:mime-version:x-gm-gg:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to:content-type; bh=untlsWKCmUskRJ6IcVNxtDJPP7daDw4oG9bUyYqHSdU=; b=AXW9Rd7q3kz8P/Z68o5sKo6B5LTJwr7VwE5JDeFXUOfrWbiROZNC3//2016AtA8KNG y2wNQ1disJAv51NHhxfe36HTsWC0cX6A37zOfQAGTmb7LAKeAOC2d2DhoZZw1ajpVY9U ic33M28WWmr2/6bWWLLZKyP9lBIJNy7s0Ny1mxHgPsV8HsbCGUX9UWQutQMV18FVXc/l 4ZMjYXAcrynPVR9Qw2Yg5vyky09rs5rNw4gvsUA1FOkTT3jx8zzHCfsxIJNKXqCREtrm DyUenhPYDWR8+UOoNV8cF5ocPSEKuPytTG+vM62XWf4Ae6Y5onWFIKYk2UpwcwuW/ZKW 7Ehw== X-Forwarded-Encrypted: i=1; AHgh+RrzhBixVjeG1JYLbt3T9Wxnbv+MjjG9n2a4QS+jEFgXxgxs0RNeQSq8ZBptPc13szRhaHZqHMozP9NE4Rgh3XpZGPKbnw==@freebsd.org X-Gm-Message-State: AOJu0Yy04Z4mHHtffgnDb86sV+PmJc5ol8TF8vH1lnPqfDNCHtSQ1r6t C7+DEYURFnQ4fXYzEP4GxZKBCxJI7+mKfJRIPrxISvUG8C314R1RAW18kW92AmEYP043kZIzFBy SxwXjEsVVDqPKtBjrJLGtQ0S2dBUxbJLezg== X-Gm-Gg: AR+sD12a4sh4Aq+H5LR8JKtANoEmnLtx+JMKHu0191E88yuhSkLEKW/gzx8+I2mN+sH OISiGawZyzh/baezRmD7YPZB68ulYc6NXlZpBroN9bmZ3qcgpyeyELbEcCVLsz4mjYq9isW0REd MSbN5J87glGChbLDj6O/Q3EkoTkMtuD5cIAXHOBPqw11lT2MVcm0oRrDNn33Vk3JM3A9SmTlf6d B0ZmZ0X75eP+L1bFc4NcdmRe0V88h1BwQNL+VbjdNErbN16yTFjqmsq/vXo1vKmvzSufi+BUwzD sTy3ZBsu1oTtUKY35OZQ697tWFlF4qCLLAys8uptJaDViylY4q0UDgFfm3AQgAeZazgUgBdI3dw 0rxu9rSUZ X-Received: by 2002:a05:690c:ecb:b0:81e:8383:851c with SMTP id 00721157ae682-824413518d9mr162581227b3.13.1786404729412; Mon, 10 Aug 2026 16:32:09 -0700 (PDT) List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Received: by 2002:a05:7010:74a3:b0:544:192b:8a02 with HTTP; Mon, 10 Aug 2026 16:32:07 -0700 (PDT) In-Reply-To: References: <6a782292.1895b.72e40e68@gitrepo.freebsd.org> From: Oliver Pinter Date: Tue, 11 Aug 2026 01:32:07 +0200 X-Gm-Features: AUfX_mwdnKOQ4z49-nE3j3zHTm71errgVdzQdxXqjb83GtcEdRA9Nk_mqZ9lpo0 Message-ID: Subject: Re: git: 6f8b3be1fbd6 - main - pci: Add SR-IOV status reporting To: Kevin Bowling Cc: Kevin Bowling , "src-committers@freebsd.org" , "dev-commits-src-all@freebsd.org" , "dev-commits-src-main@freebsd.org" Content-Type: multipart/alternative; boundary="000000000000525fe10658b9c3df" X-Rspamd-Queue-Id: 4hJrd619Llz41yh X-Rspamd-Pre-Result: action=no action; module=replies; Message is reply to one we originated X-Spamd-Result: default: False [-4.00 / 15.00]; REPLY(-4.00)[]; TAGGED_FROM(0.00)[]; ASN(0.00)[asn:15169, ipnet:2607:f8b0::/32, country:US] X-Spamd-Bar: ---- --000000000000525fe10658b9c3df Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Tuesday, August 11, 2026, Kevin Bowling wrote= : > On Mon, Aug 10, 2026 at 3:52=E2=80=AFPM Oliver Pinter > wrote: > > > > > > > > On Sunday, August 9, 2026, Kevin Bowling wrote: > >> > >> The branch main has been updated by kbowling: > >> > >> URL: https://cgit.FreeBSD.org/src/commit/?id=3D > 6f8b3be1fbd661bfa11c55081851c36ee1d5d2c1 > >> > >> commit 6f8b3be1fbd661bfa11c55081851c36ee1d5d2c1 > >> Author: Kevin Bowling > >> AuthorDate: 2026-08-09 02:03:49 +0000 > >> Commit: Kevin Bowling > >> CommitDate: 2026-08-09 06:46:41 +0000 > >> > >> pci: Add SR-IOV status reporting > >> > >> Add a generic packed-nvlist status query to each /dev/iov/ > >> control device. Report the live VF Enable state, configured and > total > >> VF counts, and one record for each configured VF. > >> > >> Each VF record contains its PF-local index, computed PCI location, > >> newbus attachment state, attached driver, and ppt binding. > Construct > >> records for hardware VFs whose newbus child is absent so attachmen= t > >> failures remain visible. > >> > >> Version the extensible schema in sys/iov.h. Use fixed-width reque= st > >> fields so the ioctl command and layout are identical for 32-bit > callers. > >> Serialize the topology snapshot with Giant, then pack and copy it > after > >> releasing Giant. > > > > > > Hi! > > > > Just curiosity, why introducing Giant lock usage in FreeBSD in 2026? > Wasn't there some very heavy efforts to kill it with fire from the kernel > before? > > Did you look at > https://cgit.freebsd.org/src/tree/sys/dev/pci/pci_iov.c? > Not yet, but thanks for the pointer! > It's the required topology lock. > I thought SR-IOV is a relatively new framework in the kernel, I was wrong. Seems like the Giant-reaping doesn't reached it yet. > > Take another look and see if you can help. > > >> > >> --- > >> sys/dev/pci/pci_iov.c | 174 ++++++++++++++++++++++++++++++ > +++++++++++++++++++- > >> sys/sys/iov.h | 46 +++++++++++++ > >> 2 files changed, 219 insertions(+), 1 deletion(-) > >> > >> diff --git a/sys/dev/pci/pci_iov.c b/sys/dev/pci/pci_iov.c > >> index 643f0e59b9b8..00a9c8e8be72 100644 > >> --- a/sys/dev/pci/pci_iov.c > >> +++ b/sys/dev/pci/pci_iov.c > >> @@ -27,6 +27,7 @@ > >> #include > >> #include "opt_bus.h" > >> > >> +#include > >> #include > >> #include > >> #include > >> @@ -875,6 +876,129 @@ pci_iov_is_child_vf(struct pcicfg_iov *pf, > device_t child) > >> return (pf =3D=3D vfinfo->cfg.iov); > >> } > >> > >> +static int > >> +pci_iov_build_status(struct pci_devinfo *dinfo, nvlist_t **statusp) > >> +{ > >> + const char *driver; > >> + device_t bus, child, dev, pcib, *devlist, *vfdevs; > >> + nvlist_t *pf, *status, **vfs; > >> + struct pcicfg_iov *iov; > >> + struct pci_devinfo *vfinfo; > >> + bool attached, passthrough; > >> + int busno, devcount, error, func, i, slot; > >> + uint16_t rid_off, rid_stride, vf_rid; > >> + > >> + mtx_assert(&Giant, MA_OWNED); > >> + > >> + iov =3D dinfo->cfg.iov; > >> + dev =3D dinfo->cfg.dev; > >> + bus =3D device_get_parent(dev); > >> + pcib =3D device_get_parent(bus); > >> + devlist =3D NULL; > >> + vfdevs =3D NULL; > >> + vfs =3D NULL; > >> + status =3D NULL; > >> + pf =3D NULL; > >> + error =3D 0; > >> + > >> + if (iov->iov_num_vfs !=3D 0) { > >> + vfdevs =3D mallocarray(iov->iov_num_vfs, sizeof(*vfdev= s), > >> + M_SRIOV, M_WAITOK | M_ZERO); > >> + error =3D device_get_children(bus, &devlist, &devcount= ); > >> + if (error !=3D 0) > >> + goto out; > >> + for (i =3D 0; i < devcount; i++) { > >> + child =3D devlist[i]; > >> + if (!pci_iov_is_child_vf(iov, child)) > >> + continue; > >> + vfinfo =3D device_get_ivars(child); > >> + if (vfinfo->cfg.vf.index < iov->iov_num_vfs) > >> + vfdevs[vfinfo->cfg.vf.index] =3D child= ; > >> + } > >> + } > >> + > >> + status =3D nvlist_create(0); > >> + pf =3D nvlist_create(0); > >> + if (status =3D=3D NULL || pf =3D=3D NULL) { > >> + error =3D ENOMEM; > >> + goto out; > >> + } > >> + nvlist_add_number(status, IOV_STATUS_VERSION_NAME, > IOV_STATUS_VERSION); > >> + nvlist_add_string(pf, IOV_STATUS_DEVICE_NAME, > device_get_nameunit(dev)); > >> + nvlist_add_stringf(pf, IOV_STATUS_PCI_LOCATION_NAME, > "pci%u:%u:%u:%u", > >> + (u_int)pci_get_domain(dev), (u_int)pci_get_bus(dev), > >> + (u_int)pci_get_slot(dev), (u_int)pci_get_function(dev)); > >> + nvlist_add_bool(pf, IOV_STATUS_ENABLED_NAME, > >> + (IOV_READ(dinfo, PCIR_SRIOV_CTL, 2) & PCIM_SRIOV_VF_EN) != =3D > 0); > >> + nvlist_add_number(pf, IOV_STATUS_NUM_VFS_NAME, > iov->iov_num_vfs); > >> + nvlist_add_number(pf, IOV_STATUS_TOTAL_VFS_NAME, > >> + IOV_READ(dinfo, PCIR_SRIOV_TOTAL_VFS, 2)); > >> + error =3D nvlist_error(pf); > >> + if (error !=3D 0) > >> + goto out; > >> + nvlist_move_nvlist(status, IOV_STATUS_PF_NAME, pf); > >> + pf =3D NULL; > >> + > >> + if (iov->iov_num_vfs !=3D 0) > >> + vfs =3D mallocarray(iov->iov_num_vfs, sizeof(*vfs), > M_SRIOV, > >> + M_WAITOK | M_ZERO); > >> + rid_off =3D IOV_READ(dinfo, PCIR_SRIOV_VF_OFF, 2); > >> + rid_stride =3D IOV_READ(dinfo, PCIR_SRIOV_VF_STRIDE, 2); > >> + vf_rid =3D pci_get_rid(dev) + rid_off; > >> + for (i =3D 0; i < iov->iov_num_vfs; i++, vf_rid +=3D rid_strid= e) { > >> + vfs[i] =3D nvlist_create(0); > >> + if (vfs[i] =3D=3D NULL) { > >> + error =3D ENOMEM; > >> + goto out; > >> + } > >> + nvlist_add_number(vfs[i], IOV_STATUS_VF_INDEX_NAME, i)= ; > >> + child =3D vfdevs[i]; > >> + if (child !=3D NULL) { > >> + busno =3D pci_get_bus(child); > >> + slot =3D pci_get_slot(child); > >> + func =3D pci_get_function(child); > >> + } else > >> + PCIB_DECODE_RID(pcib, vf_rid, &busno, &slot, > &func); > >> + nvlist_add_stringf(vfs[i], IOV_STATUS_PCI_LOCATION_NAM= E, > >> + "pci%u:%u:%u:%u", (u_int)pci_get_domain(dev), > >> + (u_int)busno, (u_int)slot, (u_int)func); > >> + attached =3D child !=3D NULL && device_is_attached(chi= ld); > >> + passthrough =3D child !=3D NULL && device_get_name(chi= ld) > !=3D NULL && > >> + strcmp(device_get_name(child), "ppt") =3D=3D 0; > >> + nvlist_add_bool(vfs[i], IOV_STATUS_ATTACHED_NAME, > attached); > >> + nvlist_add_bool(vfs[i], IOV_STATUS_PASSTHROUGH_NAME, > >> + passthrough); > >> + if (attached) { > >> + driver =3D device_get_nameunit(child); > >> + if (driver !=3D NULL) > >> + nvlist_add_string(vfs[i], > >> + IOV_STATUS_BOUND_DRIVER_NAME, > driver); > >> + } > >> + error =3D nvlist_error(vfs[i]); > >> + if (error !=3D 0) > >> + goto out; > >> + } > >> + if (iov->iov_num_vfs !=3D 0) > >> + nvlist_add_nvlist_array(status, IOV_STATUS_VFS_NAME, > >> + (const nvlist_t * const *)vfs, iov->iov_num_vfs); > >> + error =3D nvlist_error(status); > >> + if (error !=3D 0) > >> + goto out; > >> + *statusp =3D status; > >> + status =3D NULL; > >> +out: > >> + if (vfs !=3D NULL) { > >> + for (i =3D 0; i < iov->iov_num_vfs; i++) > >> + nvlist_destroy(vfs[i]); > >> + free(vfs, M_SRIOV); > >> + } > >> + nvlist_destroy(pf); > >> + nvlist_destroy(status); > >> + free(vfdevs, M_SRIOV); > >> + free(devlist, M_TEMP); > >> + return (error); > >> +} > >> + > >> static int > >> pci_iov_delete_iov_children(struct pci_devinfo *dinfo) > >> { > >> @@ -985,7 +1109,8 @@ pci_iov_get_schema_ioctl(struct cdev *cdev, > struct pci_iov_schema *output) > >> { > >> struct pci_devinfo *dinfo; > >> void *packed; > >> - size_t output_len, size; > >> + size_t size; > >> + uint64_t output_len; > >> int error; > >> > >> packed =3D NULL; > >> @@ -1025,6 +1150,50 @@ fail: > >> return (error); > >> } > >> > >> +static int > >> +pci_iov_get_status_ioctl(struct cdev *cdev, struct pci_iov_status > *output) > >> +{ > >> + struct pci_devinfo *dinfo; > >> + nvlist_t *status; > >> + void *packed; > >> + size_t output_len, size; > >> + int error; > >> + > >> + status =3D NULL; > >> + packed =3D NULL; > >> + if (output->reserved !=3D 0) > >> + return (EINVAL); > >> + mtx_lock(&Giant); > >> + dinfo =3D cdev->si_drv1; > >> + error =3D pci_iov_build_status(dinfo, &status); > >> + mtx_unlock(&Giant); > >> + if (error !=3D 0) > >> + goto out; > >> + > >> + packed =3D nvlist_pack(status, &size); > >> + if (packed =3D=3D NULL) { > >> + error =3D ENOMEM; > >> + goto out; > >> + } > >> + > >> + output_len =3D output->len; > >> + output->len =3D size; > >> + if (size <=3D output_len) { > >> + error =3D copyout(packed, PTRIN(output->status), size)= ; > >> + if (error !=3D 0) > >> + goto out; > >> + output->error =3D 0; > >> + } else { > >> + /* Keep the ioctl successful so the required size is > copied out. */ > >> + output->error =3D EMSGSIZE; > >> + } > >> + error =3D 0; > >> +out: > >> + free(packed, M_NVLIST); > >> + nvlist_destroy(status); > >> + return (error); > >> +} > >> + > >> static int > >> pci_iov_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, > >> struct thread *td) > >> @@ -1038,6 +1207,9 @@ pci_iov_ioctl(struct cdev *dev, u_long cmd, > caddr_t data, int fflag, > >> case IOV_GET_SCHEMA: > >> return (pci_iov_get_schema_ioctl(dev, > >> (struct pci_iov_schema *)data)); > >> + case IOV_GET_STATUS: > >> + return (pci_iov_get_status_ioctl(dev, > >> + (struct pci_iov_status *)data)); > >> default: > >> return (EINVAL); > >> } > >> diff --git a/sys/sys/iov.h b/sys/sys/iov.h > >> index 2ae7e5ac6767..67a890bba66f 100644 > >> --- a/sys/sys/iov.h > >> +++ b/sys/sys/iov.h > >> @@ -164,6 +164,51 @@ struct pci_iov_schema > >> int error; > >> }; > >> > >> +/* > >> + * IOV_GET_STATUS schema contract. > >> + * > >> + * The top-level nvlist contains a version number, a PF nvlist, and, > when VFs > >> + * are configured, an array of per-VF nvlists. The "vfs" key is > omitted when > >> + * "num-vfs" is zero; its absence therefore means no VFs are > configured. The > >> + * PF record identifies the device, reports the live SR-IOV VF Enable > state, > >> + * and gives the number of VFs configured by the PCI IOV framework an= d > the > >> + * hardware limit. When present, the array contains one VF record fo= r > each > >> + * configured VF, even when its newbus child could not be attached. > >> + * > >> + * PCI locations use FreeBSD's native decimal pciD:B:S:F notation (fo= r > >> + * example, pci0:2:16:2). "attached" means that newbus successfully > attached > >> + * a driver. "bound-driver" is present only for an attached VF and > contains > >> + * the driver's nameunit. "passthrough" means that the VF has the pp= t > host > >> + * devclass; it does not imply that a running virtual machine > currently owns > >> + * the VF. > >> + * > >> + * Consumers must ignore unknown keys. Additive optional keys retain > the > >> + * status version; incompatible type or structural changes require a > new > >> + * version. > >> + */ > >> +#define IOV_STATUS_VERSION 1 > >> +#define IOV_STATUS_VERSION_NAME "version" > >> +#define IOV_STATUS_PF_NAME "pf" > >> +#define IOV_STATUS_VFS_NAME "vfs" > >> +#define IOV_STATUS_DEVICE_NAME "device" > >> +#define IOV_STATUS_PCI_LOCATION_NAME "pci-location" > >> +#define IOV_STATUS_ENABLED_NAME "enabled" > >> +#define IOV_STATUS_NUM_VFS_NAME "num-vfs" > >> +#define IOV_STATUS_TOTAL_VFS_NAME "total-vfs" > >> +#define IOV_STATUS_VF_INDEX_NAME "index" > >> +#define IOV_STATUS_ATTACHED_NAME "attached" > >> +#define IOV_STATUS_BOUND_DRIVER_NAME "bound-driver" > >> +#define IOV_STATUS_PASSTHROUGH_NAME "passthrough" > >> + > >> +/* Fixed-width fields keep the ioctl ABI identical for 32-bit callers= . > */ > >> +struct pci_iov_status > >> +{ > >> + uint64_t status; /* User pointer to the packed nvlist. = */ > >> + uint64_t len; > >> + int32_t error; > >> + uint32_t reserved; /* Must be zero. */ > >> +}; > >> + > >> /* > >> * SR-IOV configuration is passed to the kernel as a packed nvlist. > See nv(3) > >> * for the details of the nvlist API. The expected format of the > nvlist is: > >> @@ -254,5 +299,6 @@ struct pci_iov_arg > >> #define IOV_CONFIG _IOW('p', 10, struct pci_iov_arg) > >> #define IOV_DELETE _IO('p', 11) > >> #define IOV_GET_SCHEMA _IOWR('p', 12, struct pci_iov_schema) > >> +#define IOV_GET_STATUS _IOWR('p', 13, struct pci_iov_status) > >> > >> #endif > >> > --000000000000525fe10658b9c3df Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable

On Tuesday, August 11, 2026, Kevin Bowling <kevin.bowling@kev009.com> wrote:
On Mon, Aug 10, 2026 at 3:52=E2=80=AFPM Oliver Pinte= r <oliver.pntr@gmail.com>= ; wrote:
>
>
>
> On Sunday, August 9, 2026, Kevin Bowling <kbowling@freebsd.org> wrote:
>>
>> The branch main has been updated by kbowling:
>>
>> URL: https://cgit.FreeBSD.or= g/src/commit/?id=3D6f8b3be1fbd661bfa11c55081851c36ee1d5d2c1<= /a>
>>
>> commit 6f8b3be1fbd661bfa11c55081851c36ee1d5d2c1
>> Author:=C2=A0 =C2=A0 =C2=A0Kevin Bowling <kbowling@FreeBSD.org&= gt;
>> AuthorDate: 2026-08-09 02:03:49 +0000
>> Commit:=C2=A0 =C2=A0 =C2=A0Kevin Bowling <kbowling@FreeBSD.org&= gt;
>> CommitDate: 2026-08-09 06:46:41 +0000
>>
>>=C2=A0 =C2=A0 =C2=A0pci: Add SR-IOV status reporting
>>
>>=C2=A0 =C2=A0 =C2=A0Add a generic packed-nvlist status query to eac= h /dev/iov/<PF>
>>=C2=A0 =C2=A0 =C2=A0control device.=C2=A0 Report the live VF Enable= state, configured and total
>>=C2=A0 =C2=A0 =C2=A0VF counts, and one record for each configured V= F.
>>
>>=C2=A0 =C2=A0 =C2=A0Each VF record contains its PF-local index, com= puted PCI location,
>>=C2=A0 =C2=A0 =C2=A0newbus attachment state, attached driver, and p= pt binding.=C2=A0 Construct
>>=C2=A0 =C2=A0 =C2=A0records for hardware VFs whose newbus child is = absent so attachment
>>=C2=A0 =C2=A0 =C2=A0failures remain visible.
>>
>>=C2=A0 =C2=A0 =C2=A0Version the extensible schema in sys/iov.h.=C2= =A0 Use fixed-width request
>>=C2=A0 =C2=A0 =C2=A0fields so the ioctl command and layout are iden= tical for 32-bit callers.
>>=C2=A0 =C2=A0 =C2=A0Serialize the topology snapshot with Giant, the= n pack and copy it after
>>=C2=A0 =C2=A0 =C2=A0releasing Giant.
>
>
> Hi!
>
> Just curiosity, why introducing Giant lock usage in FreeBSD in 2026? W= asn't there some very heavy efforts to kill it with fire from the kerne= l before?

Did you look at
https://cgit.freebsd.org/src/tree/sys/dev/pci/pci_iov.c?


Not yet, but thanks for the pointer!


It'= ;s the required topology lock.
<= br>

I thought SR-IOV is a relatively new fr= amework in the kernel, I was wrong. Seems like the Giant-reaping doesn'= t reached it yet.
=C2=A0

=
Take another look and see if yo= u can help.

>>
>> ---
>>=C2=A0 sys/dev/pci/pci_iov.c | 174 +++++++++++++++++++++++++++++++++++++++++++++++++-
>>=C2=A0 sys/sys/iov.h=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0|=C2=A0 46 ++= +++++++++++
>>=C2=A0 2 files changed, 219 insertions(+), 1 deletion(-)
>>
>> diff --git a/sys/dev/pci/pci_iov.c b/sys/dev/pci/pci_iov.c
>> index 643f0e59b9b8..00a9c8e8be72 100644
>> --- a/sys/dev/pci/pci_iov.c
>> +++ b/sys/dev/pci/pci_iov.c
>> @@ -27,6 +27,7 @@
>>=C2=A0 #include <sys/cdefs.h>
>>=C2=A0 #include "opt_bus.h"
>>
>> +#include <sys/abi_compat.h>
>>=C2=A0 #include <sys/param.h>
>>=C2=A0 #include <sys/conf.h>
>>=C2=A0 #include <sys/kernel.h>
>> @@ -875,6 +876,129 @@ pci_iov_is_child_vf(struct pcicfg_iov *pf, d= evice_t child)
>>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (pf =3D=3D vfinfo->cfg.= iov);
>>=C2=A0 }
>>
>> +static int
>> +pci_iov_build_status(struct pci_devinfo *dinfo, nvlist_t **status= p)
>> +{
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0const char *driver;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0device_t bus, child, dev, pcib, *devli= st, *vfdevs;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0nvlist_t *pf, *status, **vfs;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0struct pcicfg_iov *iov;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0struct pci_devinfo *vfinfo;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0bool attached, passthrough;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0int busno, devcount, error, func, i, s= lot;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0uint16_t rid_off, rid_stride, vf_rid;<= br> >> +
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0mtx_assert(&Giant, MA_OWNED);
>> +
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0iov =3D dinfo->cfg.iov;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0dev =3D dinfo->
cfg.dev;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0bus =3D device_get_parent(dev);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0pcib =3D device_get_parent(bus);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0devlist =3D NULL;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0vfdevs =3D NULL;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0vfs =3D NULL;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0status =3D NULL;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0pf =3D NULL;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0error =3D 0;
>> +
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0if (iov->iov_num_vfs !=3D 0) {
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0vfdevs =3D= mallocarray(iov->iov_num_vfs, sizeof(*vfdevs),
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0M_SRIOV, M_WAITOK | M_ZERO);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0error =3D = device_get_children(bus, &devlist, &devcount);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if (error = !=3D 0)
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0goto out;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0for (i =3D= 0; i < devcount; i++) {
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0child =3D devlist[i];
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0if (!pci_iov_is_child_vf(iov, child))
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0continue;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0vfinfo =3D device_get_ivars(child);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0if (vfinfo->cfg.vf.index < iov->iov_num_vfs) >> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0vfdevs[vfinfo->cfg.vf.in= dex] =3D child;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0}
>> +
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0status =3D nvlist_create(0);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0pf =3D nvlist_create(0);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0if (status =3D=3D NULL || pf =3D=3D NU= LL) {
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0error =3D = ENOMEM;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0goto out;<= br> >> +=C2=A0 =C2=A0 =C2=A0 =C2=A0}
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0nvlist_add_number(status, IOV_STATUS_V= ERSION_NAME, IOV_STATUS_VERSION);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0nvlist_add_string(pf, IOV_STATUS_DEVIC= E_NAME, device_get_nameunit(dev));
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0nvlist_add_stringf(pf, IOV_STATUS_PCI_= LOCATION_NAME, "pci%u:%u:%u:%u",
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(u_int)pci_get_domain(de= v), (u_int)pci_get_bus(dev),
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(u_int)pci_get_slot(dev)= , (u_int)pci_get_function(dev));
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0nvlist_add_bool(pf, IOV_STATUS_ENABLED= _NAME,
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(IOV_READ(dinfo, PCIR_SR= IOV_CTL, 2) & PCIM_SRIOV_VF_EN) !=3D 0);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0nvlist_add_number(pf, IOV_STATUS_NUM_V= FS_NAME, iov->iov_num_vfs);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0nvlist_add_number(pf, IOV_STATUS_TOTAL= _VFS_NAME,
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0IOV_READ(dinfo, PCIR_SRI= OV_TOTAL_VFS, 2));
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0error =3D nvlist_error(pf);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0if (error !=3D 0)
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0goto out;<= br> >> +=C2=A0 =C2=A0 =C2=A0 =C2=A0nvlist_move_nvlist(status, IOV_STATUS_= PF_NAME, pf);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0pf =3D NULL;
>> +
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0if (iov->iov_num_vfs !=3D 0)
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0vfs =3D ma= llocarray(iov->iov_num_vfs, sizeof(*vfs), M_SRIOV,
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0M_WAITOK | M_ZERO);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0rid_off =3D IOV_READ(dinfo, PCIR_SRIOV= _VF_OFF, 2);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0rid_stride =3D IOV_READ(dinfo, PCIR_SR= IOV_VF_STRIDE, 2);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0vf_rid =3D pci_get_rid(dev) + rid_off;=
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0for (i =3D 0; i < iov->iov_num_v= fs; i++, vf_rid +=3D rid_stride) {
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0vfs[i] =3D= nvlist_create(0);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if (vfs[i]= =3D=3D NULL) {
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0error =3D ENOMEM;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0goto out;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0nvlist_add= _number(vfs[i], IOV_STATUS_VF_INDEX_NAME, i);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0child =3D = vfdevs[i];
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if (child = !=3D NULL) {
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0busno =3D pci_get_bus(child);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0slot =3D pci_get_slot(child);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0func =3D pci_get_function(child);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0} else
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0PCIB_DECODE_RID(pcib, vf_rid, &busno, &slot, &a= mp;func);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0nvlist_add= _stringf(vfs[i], IOV_STATUS_PCI_LOCATION_NAME,
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0"pci%u:%u:%u:%u", (u_int)pci_get_domain(dev),
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0(u_int)busno, (u_int)slot, (u_int)func);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0attached = =3D child !=3D NULL && device_is_attached(child);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0passthroug= h =3D child !=3D NULL && device_get_name(child) !=3D NULL &&= ;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0strcmp(device_get_name(child), "ppt") =3D=3D 0;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0nvlist_add= _bool(vfs[i], IOV_STATUS_ATTACHED_NAME, attached);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0nvlist_add= _bool(vfs[i], IOV_STATUS_PASSTHROUGH_NAME,
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0passthrough);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if (attach= ed) {
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0driver =3D device_get_nameunit(child);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0if (driver !=3D NULL)
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0nvlist_add_string(vfs[i], >> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0IOV_STATUS_BO= UND_DRIVER_NAME, driver);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0error =3D = nvlist_error(vfs[i]);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if (error = !=3D 0)
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0goto out;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0}
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0if (iov->iov_num_vfs !=3D 0)
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0nvlist_add= _nvlist_array(status, IOV_STATUS_VFS_NAME,
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0(const nvlist_t * const *)vfs, iov->iov_num_vfs);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0error =3D nvlist_error(status);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0if (error !=3D 0)
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0goto out;<= br> >> +=C2=A0 =C2=A0 =C2=A0 =C2=A0*statusp =3D status;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0status =3D NULL;
>> +out:
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0if (vfs !=3D NULL) {
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0for (i =3D= 0; i < iov->iov_num_vfs; i++)
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0nvlist_destroy(vfs[i]);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0free(vfs, = M_SRIOV);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0}
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0nvlist_destroy(pf);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0nvlist_destroy(status);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0free(vfdevs, M_SRIOV);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0free(devlist, M_TEMP);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0return (error);
>> +}
>> +
>>=C2=A0 static int
>>=C2=A0 pci_iov_delete_iov_children(struct pci_devinfo *dinfo)<= br> >>=C2=A0 {
>> @@ -985,7 +1109,8 @@ pci_iov_get_schema_ioctl(struct cdev *cd= ev, struct pci_iov_schema *output)
>>=C2=A0 {
>>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0struct pci_devinfo *dinfo;
>>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0void *packed;
>> -=C2=A0 =C2=A0 =C2=A0 =C2=A0size_t output_len, size;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0size_t size;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0uint64_t output_len;
>>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0int error;
>>
>>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0packed =3D NULL;
>> @@ -1025,6 +1150,50 @@ fail:
>>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (error);
>>=C2=A0 }
>>
>> +static int
>> +pci_iov_get_status_ioctl(struct cdev *cdev, struct pci_iov_s= tatus *output)
>> +{
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0struct pci_devinfo *dinfo;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0nvlist_t *status;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0void *packed;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0size_t output_len, size;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0int error;
>> +
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0status =3D NULL;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0packed =3D NULL;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0if (output->reserved !=3D 0)
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (EI= NVAL);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0mtx_lock(&Giant);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0dinfo =3D cdev->si_drv1;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0error =3D pci_iov_build_status(dinfo, = &status);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0mtx_unlock(&Giant);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0if (error !=3D 0)
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0goto out;<= br> >> +
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0packed =3D nvlist_pack(status, &si= ze);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0if (packed =3D=3D NULL) {
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0error =3D = ENOMEM;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0goto out;<= br> >> +=C2=A0 =C2=A0 =C2=A0 =C2=A0}
>> +
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0output_len =3D output->len;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0output->len =3D size;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0if (size <=3D output_len) {
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0error =3D = copyout(packed, PTRIN(output->status), size);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if (error = !=3D 0)
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0goto out;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0output->= ;error =3D 0;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0} else {
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/* Keep th= e ioctl successful so the required size is copied out. */
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0output->= ;error =3D EMSGSIZE;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0}
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0error =3D 0;
>> +out:
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0free(packed, M_NVLIST);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0nvlist_destroy(status);
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0return (error);
>> +}
>> +
>>=C2=A0 static int
>>=C2=A0 pci_iov_ioctl(struct cdev *dev, u_long cmd, caddr_t data, in= t fflag,
>>=C2=A0 =C2=A0 =C2=A0 struct thread *td)
>> @@ -1038,6 +1207,9 @@ pci_iov_ioctl(struct cdev *dev, u_long cmd, = caddr_t data, int fflag,
>>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0case IOV_GET_SCHEMA:
>>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0retur= n (pci_iov_get_schema_ioctl(dev,
>>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0(struct pci_iov_schema *)data));
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0case IOV_GET_STATUS:
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (pc= i_iov_get_status_ioctl(dev,
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0(struct pci_iov_status *)data));
>>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0default:
>>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0retur= n (EINVAL);
>>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}
>> diff --git a/sys/sys/iov.h b/sys/sys/iov.h
>> index 2ae7e5ac6767..67a890bba66f 100644
>> --- a/sys/sys/iov.h
>> +++ b/sys/sys/iov.h
>> @@ -164,6 +164,51 @@ struct pci_iov_schema
>>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0int error;
>>=C2=A0 };
>>
>> +/*
>> + * IOV_GET_STATUS schema contract.
>> + *
>> + * The top-level nvlist contains a version number, a PF nvlist, a= nd, when VFs
>> + * are configured, an array of per-VF nvlists.=C2=A0 The "vf= s" key is omitted when
>> + * "num-vfs" is zero; its absence therefore means no VF= s are configured.=C2=A0 The
>> + * PF record identifies the device, reports the live SR-IOV VF En= able state,
>> + * and gives the number of VFs configured by the PCI IOV framewor= k and the
>> + * hardware limit.=C2=A0 When present, the array contains one VF = record for each
>> + * configured VF, even when its newbus child could not be attache= d.
>> + *
>> + * PCI locations use FreeBSD's native decimal pciD:B:S:F nota= tion (for
>> + * example, pci0:2:16:2).=C2=A0 "attached" means that n= ewbus successfully attached
>> + * a driver.=C2=A0 "bound-driver" is present only for a= n attached VF and contains
>> + * the driver's nameunit.=C2=A0 "passthrough" means= that the VF has the ppt host
>> + * devclass; it does not imply that a running virtual machine cur= rently owns
>> + * the VF.
>> + *
>> + * Consumers must ignore unknown keys.=C2=A0 Additive optional ke= ys retain the
>> + * status version; incompatible type or structural changes requir= e a new
>> + * version.
>> + */
>> +#define=C2=A0 =C2=A0 =C2=A0 =C2=A0 IOV_STATUS_VERSION=C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 1
>> +#define=C2=A0 =C2=A0 =C2=A0 =C2=A0 IOV_STATUS_VERSION_NAME=C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0"version"
>> +#define=C2=A0 =C2=A0 =C2=A0 =C2=A0 IOV_STATUS_PF_NAME=C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 "pf"
>> +#define=C2=A0 =C2=A0 =C2=A0 =C2=A0 IOV_STATUS_VFS_NAME=C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0"vfs"
>> +#define=C2=A0 =C2=A0 =C2=A0 =C2=A0 IOV_STATUS_DEVICE_NAME=C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 "device"
>> +#define=C2=A0 =C2=A0 =C2=A0 =C2=A0 IOV_STATUS_PCI_LOCATION_NAME= =C2=A0 =C2=A0 "pci-location"
>> +#define=C2=A0 =C2=A0 =C2=A0 =C2=A0 IOV_STATUS_ENABLED_NAME=C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0"enabled"
>> +#define=C2=A0 =C2=A0 =C2=A0 =C2=A0 IOV_STATUS_NUM_VFS_NAME=C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0"num-vfs"
>> +#define=C2=A0 =C2=A0 =C2=A0 =C2=A0 IOV_STATUS_TOTAL_VFS_NAME=C2= =A0 =C2=A0 =C2=A0 =C2=A0"total-vfs"
>> +#define=C2=A0 =C2=A0 =C2=A0 =C2=A0 IOV_STATUS_VF_INDEX_NAME=C2=A0= =C2=A0 =C2=A0 =C2=A0 "index"
>> +#define=C2=A0 =C2=A0 =C2=A0 =C2=A0 IOV_STATUS_ATTACHED_NAME=C2=A0= =C2=A0 =C2=A0 =C2=A0 "attached"
>> +#define=C2=A0 =C2=A0 =C2=A0 =C2=A0 IOV_STATUS_BOUND_DRIVER_NAME= =C2=A0 =C2=A0 "bound-driver"
>> +#define=C2=A0 =C2=A0 =C2=A0 =C2=A0 IOV_STATUS_PASSTHROUGH_NAME=C2= =A0 =C2=A0 =C2=A0"passthrough"
>> +
>> +/* Fixed-width fields keep the ioctl ABI identical for 32-bit cal= lers. */
>> +struct pci_iov_status
>> +{
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0uint64_t status;=C2=A0 =C2=A0 =C2=A0 = =C2=A0 /* User pointer to the packed nvlist. */
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0uint64_t len;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0int32_t error;
>> +=C2=A0 =C2=A0 =C2=A0 =C2=A0uint32_t reserved;=C2=A0 =C2=A0 =C2=A0= /* Must be zero. */
>> +};
>> +
>>=C2=A0 /*
>>=C2=A0 =C2=A0* SR-IOV configuration is passed to the kernel as a pa= cked nvlist.=C2=A0 See nv(3)
>>=C2=A0 =C2=A0* for the details of the nvlist API.=C2=A0 The expecte= d format of the nvlist is:
>> @@ -254,5 +299,6 @@ struct pci_iov_arg
>>=C2=A0 #define=C2=A0 =C2=A0 =C2=A0 =C2=A0 IOV_CONFIG=C2=A0 =C2=A0 = =C2=A0 _IOW('p', 10, struct pci_iov_arg)
>>=C2=A0 #define=C2=A0 =C2=A0 =C2=A0 =C2=A0 IOV_DELETE=C2=A0 =C2=A0 = =C2=A0 _IO('p', 11)
>>=C2=A0 #define=C2=A0 =C2=A0 =C2=A0 =C2=A0 IOV_GET_SCHEMA=C2=A0 _IOW= R('p', 12, struct pci_iov_schema)
>> +#define=C2=A0 =C2=A0 =C2=A0 =C2=A0 IOV_GET_STATUS=C2=A0 _IOWR(= 9;p', 13, struct pci_iov_status)
>>
>>=C2=A0 #endif
>>
--000000000000525fe10658b9c3df--