devctl(8): A device control utility
John Baldwin
jhb at freebsd.org
Mon Jan 5 20:07:37 UTC 2015
For a long time I've wanted a way to administratively manipulate the state of
new-bus devices from userland. I think the first use case I wanted was a way
to power off the sound controller (and anything else I wasn't using) on my
first laptop (a Dell Inspiron 5000e I got back in 2000). Similarly, it would
be nice to have a way to handle "ejectable" devices (ACPI has a provision for
this, and said laptop had _EJx methods to allow one to swap a CD drive out for
a battery in a bay while the laptop was in S3). There are some other use
cases that would also be nice such as detaching a driver from a PCI device to
decide at runtime that it should be passed through to a bhyve guest (and
possibly undoing that to allow a host driver to take it back over). Forcing a
rescan of a PCI device can be useful if you are using an FPGA and would like
to alter BAR layout/sizes without having to reboot the OS. A way to force
resets at runtime might also be useful (e.g. a FLR for a PCI device). A few
weeks ago I finally sat down and started on an implementation. It can be
found here:
https://github.com/bsdjhb/freebsd/compare/devctl
Sample commands look like:
% devctl disable virtio_pci2
# detaches the driver, but leaves the device's name intact similar to
# specifying hint.virtio_pci.2.disabled=1 at boot
% devctl enable virtio_pci2
# enables a disabled device, including attaching it
% devctl detach uart1
# does a full detach, which means the device is now unnamed
% devctl attach \_SB_.PCI0.LPC.UAR1
# attaches an unattached device. A provision is made for recognizing
# device addresses via an EVENTHANDLER hook that a bus driver can
# install. Currently ACPI handles and pci selectors (ala pciconf)
# are recognized via hooks in the ACPI and PCI bus drivers.
% devctl set driver foo0 bar
# forces the 'foo0' device to use the 'bar' device class and thus
# only attach to a driver named 'bar' (assuming that 'bar' will
# probe it, this doesn't override device_probe). With some changes
# to ppt.c, this would allow one to do 'devctl set driver foo0 ppt'
# to detach a host driver and mark a device for PCI passthrough at
# runtime. I have not yet implemented a "clear driver" to reset
# back to an empty device class.
The current version also includes 'suspend' and 'resume' commands which
use bus_suspend_child() (recently added by Justin Hibbits) to suspend
(and possibly power down) individual devices.
Implementation notes:
For the kernel <-> userland interface, I chose to use ioctls. The ioctls
use a 'struct devreq' structure that is modeled on 'struct ifreq' used
for network interface ioctls in that there are a set of common fields and
a union of request-specific fields.
I would have liked to reuse /dev/devctl for this, but it is a single
purpose device intended for use by devd. If I had my druthers, I would
probably like to rename /dev/devctl to /dev/devevents or /dev/devnotify
or some such and create a new /dev/devctl for these control ioctls. Instead
what I've done for now is create a /dev/devctl2 for the new ioctls.
There is a thin library (libdevctl) that wraps the /dev/devctl2 ioctls and
provides methods like devctl_detach(), etc. The thin library even has a
manpage already.
The devctl(8) utility is then a thin wrapper around libdevctl (and does not
yet have a manpage).
Do folks have any feedback?
--
John Baldwin
More information about the freebsd-arch
mailing list