[PATCH xserver] modesetting: Allow a DRM fd to be passed on command line with -masterfd
Lyude Paul
lyude at redhat.com
Wed Jun 27 22:16:00 UTC 2018
Looks good! One nitpick I'm not 100% sure about:
On Thu, 2018-03-01 at 15:38 -0800, Keith Packard wrote:
> This lets an application open a suitable DRM device and pass the file
> descriptor to the mode setting driver through an X server command line
> option, '-masterfd'.
>
> There's a companion application, xlease, which creates a DRM master by
> leasing an output from another X server. That is available at
>
> git clone git://people.freedesktop.org/~keithp/xlease
>
> Signed-off-by: Keith Packard <keithp at keithp.com>
> ---
> hw/xfree86/common/xf86Globals.c | 2 ++
> hw/xfree86/common/xf86Priv.h | 1 +
> hw/xfree86/drivers/modesetting/driver.c | 26 +++++++++++++++++++++++++-
> hw/xfree86/drivers/modesetting/driver.h | 1 +
> hw/xfree86/os-support/linux/lnx_init.c | 22 ++++++++++++++++++++++
> 5 files changed, 51 insertions(+), 1 deletion(-)
>
> diff --git a/hw/xfree86/common/xf86Globals.c
> b/hw/xfree86/common/xf86Globals.c
> index e890f05c2..7cc7401a2 100644
> --- a/hw/xfree86/common/xf86Globals.c
> +++ b/hw/xfree86/common/xf86Globals.c
> @@ -53,6 +53,8 @@ DevPrivateKeyRec xf86ScreenKeyRec;
> ScrnInfoPtr *xf86Screens = NULL; /* List of ScrnInfos */
> ScrnInfoPtr *xf86GPUScreens = NULL; /* List of ScrnInfos */
>
> +int xf86DRMMasterFd = -1; /* Command line argument for DRM master file
> descriptor */
> +
> const unsigned char byte_reversed[256] = {
> 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
> 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
> diff --git a/hw/xfree86/common/xf86Priv.h b/hw/xfree86/common/xf86Priv.h
> index 4fe2b5f33..393af3900 100644
> --- a/hw/xfree86/common/xf86Priv.h
> +++ b/hw/xfree86/common/xf86Priv.h
> @@ -93,6 +93,7 @@ extern _X_EXPORT int xf86LogVerbose; /* log file
> verbosity level */
>
> extern ScrnInfoPtr *xf86GPUScreens; /* List of pointers to
> ScrnInfoRecs */
> extern int xf86NumGPUScreens;
> +extern _X_EXPORT int xf86DRMMasterFd; /* Command line argument
> for DRM master file descriptor */
> #ifndef DEFAULT_VERBOSE
> #define DEFAULT_VERBOSE 0
> #endif
> diff --git a/hw/xfree86/drivers/modesetting/driver.c
> b/hw/xfree86/drivers/modesetting/driver.c
> index ec2aa9a27..1d84e113d 100644
> --- a/hw/xfree86/drivers/modesetting/driver.c
> +++ b/hw/xfree86/drivers/modesetting/driver.c
> @@ -36,6 +36,7 @@
> #include <unistd.h>
> #include <fcntl.h>
> #include "xf86.h"
> +#include "xf86Priv.h"
> #include "xf86_OSproc.h"
> #include "compiler.h"
> #include "xf86Pci.h"
> @@ -194,11 +195,24 @@ modesettingEntPtr ms_ent_priv(ScrnInfoPtr scrn)
> return pPriv->ptr;
> }
>
> +static int
> +get_passed_fd(void)
> +{
> + if (xf86DRMMasterFd >= 0) {
> + xf86DrvMsg(-1, X_INFO, "Using passed DRM master file descriptor
> %d\n", xf86DRMMasterFd);
> + return dup(xf86DRMMasterFd);
> + }
> + return -1;
> +}
> +
> static int
> open_hw(const char *dev)
> {
> int fd;
>
> + if ((fd = get_passed_fd()) != -1)
> + return fd;
> +
> if (dev)
> fd = open(dev, O_RDWR, 0);
> else {
> @@ -822,6 +836,12 @@ ms_get_drm_master_fd(ScrnInfoPtr pScrn)
> return TRUE;
> }
>
> + ms->fd_passed = FALSE;
> + if ((ms->fd = get_passed_fd()) >= 0) {
> + ms->fd_passed = TRUE;
> + return TRUE;
> + }
> +
> #ifdef XSERVER_PLATFORM_BUS
> if (pEnt->location.type == BUS_PLATFORM) {
> if (pEnt->location.id.plat->flags & XF86_PDEV_SERVER_FD)
> @@ -1495,6 +1515,9 @@ SetMaster(ScrnInfoPtr pScrn)
> (ms->pEnt->location.id.plat->flags & XF86_PDEV_SERVER_FD))
> return TRUE;
>
> + if (ms->fd_passed)
> + return TRUE;
> +
> ret = drmSetMaster(ms->fd);
> if (ret)
> xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "drmSetMaster failed: %s\n",
> @@ -1746,7 +1769,8 @@ LeaveVT(ScrnInfoPtr pScrn)
> (ms->pEnt->location.id.plat->flags & XF86_PDEV_SERVER_FD))
> return;
>
> - drmDropMaster(ms->fd);
> + if (!ms->fd_passed)
> + drmDropMaster(ms->fd);
> }
>
> /*
> diff --git a/hw/xfree86/drivers/modesetting/driver.h
> b/hw/xfree86/drivers/modesetting/driver.h
> index fe835918b..6be51e01b 100644
> --- a/hw/xfree86/drivers/modesetting/driver.h
> +++ b/hw/xfree86/drivers/modesetting/driver.h
> @@ -84,6 +84,7 @@ struct ms_drm_queue {
>
> typedef struct _modesettingRec {
> int fd;
> + Bool fd_passed;
>
> int Chipset;
> EntityInfoPtr pEnt;
> diff --git a/hw/xfree86/os-support/linux/lnx_init.c b/hw/xfree86/os-
> support/linux/lnx_init.c
> index 9e5ddcd50..b654f7618 100644
> --- a/hw/xfree86/os-support/linux/lnx_init.c
> +++ b/hw/xfree86/os-support/linux/lnx_init.c
> @@ -356,6 +356,13 @@ xf86CloseConsole(void)
> close(xf86Info.consoleFd); /* make the vt-manager happy */
> }
>
> +#define CHECK_FOR_REQUIRED_ARGUMENT() \
> + if (((i + 1) >= argc) || (!argv[i + 1])) {
> \
> + ErrorF("Required argument to %s not specified\n", argv[i]); \
> + UseMsg(); \
> + FatalError("Required argument to %s not specified\n", argv[i]);
Is the double printing of "Required argument to %s not specified" here
intentional?
> \
> + }
> +
> int
> xf86ProcessArgument(int argc, char *argv[], int i)
> {
> @@ -376,6 +383,19 @@ xf86ProcessArgument(int argc, char *argv[], int i)
> }
> return 1;
> }
> +
> + if (!strcmp(argv[i], "-masterfd")) {
> + CHECK_FOR_REQUIRED_ARGUMENT();
> + if (xf86PrivsElevated())
> + FatalError("\nCannot specify -masterfd when server is
> setuid/setgid\n");
> + if (sscanf(argv[++i], "%d", &xf86DRMMasterFd) != 1) {
> + UseMsg();
> + xf86DRMMasterFd = -1;
> + return 0;
> + }
> + return 2;
> + }
> +
> return 0;
> }
>
> @@ -385,4 +405,6 @@ xf86UseMsg(void)
> ErrorF("vtXX use the specified VT number\n");
> ErrorF("-keeptty ");
> ErrorF("don't detach controlling tty (for debugging only)\n");
> + if (!xf86PrivsElevated())
> + ErrorF("-masterfd <fd> use the specified fd as the DRM
> master fd\n");
I think it would be a better idea for us to show this argument description
unconditionally, along with adding a note about setuid/setgid not being
allowed with it
> }
--
Cheers,
Lyude Paul
More information about the xorg-devel
mailing list