From owner-freebsd-arch@FreeBSD.ORG Mon Jan 5 20:07:37 2015 Return-Path: Delivered-To: arch@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 8500A610 for ; Mon, 5 Jan 2015 20:07:37 +0000 (UTC) Received: from bigwig.baldwin.cx (bigwig.baldwin.cx [IPv6:2001:470:1f11:75::1]) (using TLSv1 with cipher DHE-RSA-CAMELLIA256-SHA (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 5D1F43387 for ; Mon, 5 Jan 2015 20:07:37 +0000 (UTC) Received: from ralph.baldwin.cx (pool-173-70-85-31.nwrknj.fios.verizon.net [173.70.85.31]) by bigwig.baldwin.cx (Postfix) with ESMTPSA id 92538B913 for ; Mon, 5 Jan 2015 15:07:35 -0500 (EST) From: John Baldwin To: arch@freebsd.org Subject: devctl(8): A device control utility Date: Mon, 05 Jan 2015 15:01 -0500 Message-ID: <3200196.9ZgXApgRdA@ralph.baldwin.cx> User-Agent: KMail/4.14.2 (FreeBSD/10.1-STABLE; KDE/4.14.2; amd64; ; ) MIME-Version: 1.0 Content-Transfer-Encoding: 7Bit Content-Type: text/plain; charset="us-ascii" X-Greylist: Sender succeeded SMTP AUTH, not delayed by milter-greylist-4.2.7 (bigwig.baldwin.cx); Mon, 05 Jan 2015 15:07:35 -0500 (EST) X-BeenThere: freebsd-arch@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: Discussion related to FreeBSD architecture List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 05 Jan 2015 20:07:37 -0000 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