tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

DRM/KMS: report



[CAVEATS: Please remember that I'm not an english native speaker, and
that what follows is not a "lecture" or a judgement about what is done,
but a home made translation in some english of some of the notes---there
is more documentation to come later.
if I wanted to look at the DRM/KMS stuff, it was because I felt (and
still feel...) that I would never haved embarked in such an appalling
task to try to tame a thing like that ;-) I'm not "blaming" or
"naming and shaming"---or whatever the term is---or despising work
or people.]

3 months ago, I have engaged to take a look at the DRM/KMS object, with
the goal to ensure that the NetBSD kernel could be severed at will from
it.

Here is the report.

I will start with code for the impatients, and will continue with
documentation / comments and end with future directions (for me).

Note: I have finally taken again an Internet optical fiber connection
(after infelicities with a previous provider), so I have been able to
pull and push on a fork that is here:

https://github.com/tlaronde/src


                     WHAT IS IN THESE SOURCES

commit 6d7155061111703ed9f0bec6a39fec8794b5b8eb
Author: Thierry LARONDE <tlaronde%polynum.com@localhost>
Date:   Fri Oct 13 18:39:03 2023 +0200

    In order to allow to change, disable, enable, find or list devices
    according to a pattern (specified between slashes; can be anchored at
    beginning with '^'; at end with '$'; but no wildcard dot, or count or
    range...), the userconf parsing are modified.
    
    It works... but not for what I wanted. Giving /drm/ for example as a
    pattern will actually disable all matching devices, but since
    "radeondrmkmsfb" matches, you end up with no display at all because the
    drm is nonetheless attempted.
    
    "/kms$/" and "/drm$/" could work. But this is more a debugging feature
    (except for find or list) than something to use bluntly for the moment.
    
    Should we have /pattern/@/parent_pattern/? Or enforce a namespace
    policy?
    
    At least, one should use "list /pattern/" or "find /pattern/" before
    modifying blindly.

commit e62e0b293986bfb3a749ab499d8367b5c6a161a2
Author: Thierry LARONDE <tlaronde%polynum.com@localhost>
Date:   Thu Oct 12 18:07:13 2023 +0200

    Just add the precision that the pmap_pv_untrack() users are DRM2
    aka DRMKMS drivers (not "legacy" DRM ones).

commit 930cf9cd86c51551b7731777df2882a64ba655b7
Author: Thierry LARONDE <tlaronde%polynum.com@localhost>
Date:   Thu Oct 12 09:00:56 2023 +0200

    For consistency, what is related to monitors is not taken from
    XFree86 but taken from the latest VESA DMT (v 1.0, Rev. 13).  So
    modelines are removed, and dmt added, and the code fixed to work
    with this with no user visible change for the moment. And some
    modes not defined in the VESA DMT are put in an extradmt file, with
    fixes for Mac monitors (taken from parameters in the Linux framebuffer
    code).
    
    For consistency too, published strings like "800x600x60" are replaced
    by "800x600@60Hz" to avoid multiplying apples by oranges and
    ambiguity about exactly what the last number describes.
    
    The double scan entries were not used and are not generated.

                DRM, DRM2 aka DRM/KMS: SOME NOTES

DRM or now DRM2 (aka DRM/KMS) are inherently and heavily linked to
X11 and to Linux.  Due to the size of the thing, NetBSD is deriving
a version from the one FreeBSD tries to derive. To make things worse,
the API is changing significantly. So we can only adapt late; and, de
facto, we always drag behind.

The important thing to keep in mind is that this is heavily linked to
X11. It's not something independent.

To make things even worse, the abuse of acronyms is blurring things that
didn't need to be made even less clear. Not to mention the fact that DRM
is also used for Digital Rights Management---that has strictly nothing
to do with the thing---, DRI (a part of the X11 stuff) is also used
instead of DRM for the X11 part, and DRM2 is also referred too as 
DRM/KMS.

The "legacy" ("first" version, at least in NetBSD) DRM drivers are these
ones (for x86 ones):

#i915drm*       at drm?         # Intel i915, i945 DRM driver
#mach64drm*     at drm?         # mach64 (3D Rage Pro, Rage) DRM driver
#mgadrm*        at drm?         # Matrox G[24]00, G[45]50 DRM driver
#r128drm*       at drm?         # ATI Rage 128 DRM driver
#radeondrm*     at drm?         # ATI Radeon DRM driver
#savagedrm*     at drm?         # S3 Savage DRM driver
#sisdrm*        at drm?         # SiS DRM driver
#tdfxdrm*       at drm?         # 3dfx (voodoo) DRM driver

The drivers using the new API have sometimes "kms" in the name (for
i915, I guess to make a difference with the previous "legacy"
i915drm), but generally not, or if this is the case, this is not the
device attaching early:

# DRMKMS drivers 
i915drmkms*     at pci? dev ? function ?
intelfb*        at intelfbbus?

radeon*         at pci? dev ? function ?
radeondrmkmsfb* at radeonfbbus?

#amdgpu*        at pci? dev ? function ?
#amdgpufb*      at amdgpufbbus?

nouveau*        at pci? dev ? function ?
nouveaufb*      at nouveaufbbus?

To these, there is to be added:

vboxdrm*
  
And there is one using UMS (that is not KMS: it's the obsolete reverse):

viadrmums*

To illustrate the namespace problem, take "radeon":

radeondrm* is the legacy DRM driver and:

radeon* is the DRM2 and this is its child, the fb, that has the "kms"
substring:

radeondrmkmsfb* at radeonfbbus?

To take this last example, I have modified (see the commits above)
the userconf subroutines in order to be able to give a pattern for
disabling devices (I wanted a simple way to disable with, if possible,
one command all the devices relating to "drm"). But if this disables (on
my node) the i915drmkms, as it should, this disables "radeondrmkmsfb"
but not, of course, "radeon" leading to use of "radeon" with... nothing
displayed!

For the ARM part, the API is implemented but, from what I gather,
totally independantly from the external sources in order to use the
framebuffer.

Here are the files (not listing whether catalogs, docs, the obvious
external directories, or the makefiles) concerned by drm:

         DRM RELATED FILES (COMMENTS ARE NOTES FROM ME)

./etc/MAKEDEV.tmpl
./share/man/man4/drm.4
./share/man/man4/igmafb.4 # conflicts with genfb, agp and thus drm
./share/man/man5/boot.cfg.5 # disabling i915 nouveau radeon
./share/man/man8/MAKEDEV.8
./share/man/man8/compat_netbsd32.8 # no drm
./sys/arch/amd64/conf/ALL
./sys/arch/amd64/conf/GENERIC
./sys/arch/amd64/conf/INSTALL
./sys/arch/amd64/conf/XEN3_DOM0
./sys/arch/arm/nvidia/files.tegra
./sys/arch/arm/nvidia/tegra_drm.c
./sys/arch/arm/nvidia/tegra_drm.h
./sys/arch/arm/nvidia/tegra_drm_fb.c
./sys/arch/arm/nvidia/tegra_drm_mode.c
./sys/arch/arm/nvidia/tegra_fb.c
./sys/arch/arm/nvidia/tegra_nouveau.c
./sys/arch/arm/nvidia/tegra_platform.c
./sys/arch/arm/nxp/files.imx # CPPFLAGS.drmkms
./sys/arch/arm/nxp/imx6_dwhdmi.c #drm/drm_crtc_helper.h
./sys/arch/arm/rockchip/files.rockchip # DRM master
./sys/arch/arm/rockchip/rk_fb.c # arm/rockchip/rk_drm.h drm/drm_drv.h...
./sys/arch/arm/rockchip/rk_anxdp.c # drm/drm_drv.h...
./sys/arch/arm/rockchip/rk_drm.c # de dicto
./sys/arch/arm/rockchip/rk_drm.h # de dicto
./sys/arch/arm/rockchip/rk_dwhdmi.c # drm/drm_drv.h drm/drm_crtc_helper.h
./sys/arch/arm/rockchip/rk_vop.c # arm/rockchip/rk_drm.h drm/*
./sys/arch/arm/ti/files.ti # tilcdc: drmkms
./sys/arch/arm/ti/ti_fb.c # drm/drm_drv.h drm/drmfb.h arm/ti/ti_lcdc.h
./sys/arch/arm/ti/ti_lcdc.c # drm/*
./sys/arch/arm/ti/ti_lcdc.h # de dicto
./sys/arch/arm/sunxi/files.sunxi # sunximixer: drmkms; sunxilcdc: drmkms
	# https://www.kernel.org/doc/html/v5.2/gpu/tinydrm.html ?
./sys/arch/arm/sunxi/sun6i_spireg.h
./sys/arch/arm/sunxi/sunxi_drm.c
./sys/arch/arm/sunxi/sunxi_drm.h
./sys/arch/arm/sunxi/sunxi_dwhdmi.c
./sys/arch/arm/sunxi/sunxi_fb.c
./sys/arch/arm/sunxi/sunxi_hdmiphy.c
./sys/arch/arm/sunxi/sunxi_hdmiphy.h
./sys/arch/arm/sunxi/sunxi_lcdc.c
./sys/arch/arm/sunxi/sunxi_mixer.c
./sys/arch/arm/sunxi/sunxi_platform.c # sunxidrm or dwhdmi
./sys/arch/evbarm/conf/GENERIC # tegradrm
./sys/arch/evbarm/conf/GENERIC64 # rkdrm rkfb # fb depends on DRM
./sys/arch/ews4800mips/include/sbd_tr2.h # DCC.drm ?
./sys/arch/i386/conf/ALL
./sys/arch/i386/conf/GENERIC
./sys/arch/i386/conf/INSTALL
./sys/arch/i386/conf/LEGACY
./sys/arch/macppc/conf/POWERMAC_G5 # radeondrmkmsfb
./sys/arch/macppc/conf/files.macppc # ofb: drm
./sys/arch/macppc/dev/ofb.c	# drm?
./sys/compat/linux/common/linux_ioctl.c # drm and video4linux2 fallthru
./sys/compat/linux32/common/linux32_ioctl.c # idem
./sys/compat/netbsd32/files.netbsd32 # drmkms commented out
./sys/compat/netbsd32/netbsd32_drm.c # de dicto
./sys/compat/netbsd32/netbsd32_ioctl.c # netbsd32_drm_ioctl() default
./sys/compat/netbsd32/netbsd32_ioctl.h
./sys/conf/files
./sys/conf/majors
./sys/dev/drm/files.drm
./sys/dev/drm/vbox_drv.c
./sys/dev/fdt/fdt_panel.c # drm/*
./sys/dev/fdt/fdt_port.h # drm_device
./sys/dev/fdt/files.fdt # panel_fdt
./sys/dev/fdt/hdmi_connector.c # drm/*
./sys/dev/hyperv/genfb_vmbus.c # attach "drm"
./sys/dev/i2c/anxedp.c # drm/*
./sys/dev/i2c/files.i2c # anxedp drmkms, drmkms_i2c
./sys/dev/i2c/tda19988.c # drm/*
./sys/dev/ic/anx_dp.c # drm/*
./sys/dev/ic/anx_dp.h 
./sys/dev/ic/dw_hdmi.c # drm/* and dev/videomode/*
./sys/dev/ic/dw_hdmi.h
./sys/dev/ic/dw_hdmi_phy.c # drm/drm_drv.h
./sys/dev/microcode/radeon/Makefile # radeondrmkms
./sys/dev/pci/agp_i810.c # However, old drm assumes... breaks that...
./sys/dev/pci/agpvar.h # XXX  horrible hack to allow drm code to use...
./sys/dev/pci/files.pci # machfb drm
./sys/dev/pci/genfb_pci.c # attach drm
./sys/dev/pci/igma.c # igma_print()
./sys/dev/pci/machfb.c # attach drm
./sys/dev/pci/radeonfb.c # attach drm
./sys/dev/pci/unichromefb.c # attach drm
./sys/dev/pci/vga_pci.c # attach drm
./sys/dev/pci/vga_pcivar.h
./sys/dev/pci/voodoofb.c # attach drm
./sys/dev/wsfb/files.wsfb # genfb drm
./sys/kern/Make.tags.inc # find name "drm"
./sys/modules/Makefile
./sys/modules/amdgpu/Makefile
./sys/modules/ati_pcigart/Makefile # old drm
./sys/modules/compat_netbsd32/Makefile # NETBSD32_DRMKMS disabled
./sys/modules/drm/Makefile # old drm
./sys/modules/drmkms/Makefile # new drm/kms
./sys/modules/drmkms/Makefile.inc
./sys/modules/drmkms/agp.h
./sys/modules/drmkms/drmkms_pci.h
./sys/modules/drmkms_agp/Makefile
./sys/modules/drmkms_linux/Makefile
./sys/modules/drmkms_pci/Makefile
./sys/modules/drmkms_sched/Makefile
./sys/modules/drmkms_ttm/Makefile
./sys/modules/i915drm/Makefile
./sys/modules/i915drm/i915drm.ioconf
./sys/modules/i915drmkms/Makefile
./sys/modules/i915drmkms/i915drmkms.ioconf
./sys/modules/mach64drm/Makefile
./sys/modules/mach64drm/mach64drm.ioconf
./sys/modules/mgadrm/Makefile
./sys/modules/mgadrm/mgadrm.ioconf
./sys/modules/r128drm/Makefile
./sys/modules/r128drm/r128drm.ioconf
./sys/modules/radeondrm/Makefile
./sys/modules/radeondrm/radeondrm.ioconf
./sys/modules/savagedrm/Makefile
./sys/modules/savagedrm/savagedrm.ioconf
./sys/modules/sisdrm/Makefile
./sys/modules/sisdrm/sisdrm.ioconf
./sys/modules/tdfxdrm/Makefile
./sys/modules/tdfxdrm/tdfxdrm.ioconf
./sys/modules/vboxdrm/Makefile
./sys/modules/vboxdrm/vboxdrm.ioconf
./sys/modules/viadrmums/Makefile
./sys/modules/viadrmums/viadrmums.ioconf
./sys/rump/librump/rumpkern/devsw.c # "drm" DONTBOTHER
./sys/rump/listsrcdirs # drm/ and drm2/ excluded if cvsmode
./sys/uvm/pmap/pmap_pvt.c # DRM graphics drivers only user

	WHAT IS REALLY "DEPENDENT" ON THE EXTERNAL DRM*

In fact, the NetBSD kernel can still be severed from the DRM* stuff.

ARM drivers have been implemented using the API but, if I'm not
mistaken, are not depending on the external implementation.

There are no syscalls added related to the DRM.

                             THE UVM

The UVM, that is in fact the main problem, has not been
touched specifically for the aliens (the Linux stuff), if I'm not
mistaken, except in one file:

./sys/uvm/pmap/pmap_pvt.c # DRM graphics drivers only user

where pmap_pv_untrack() is only used by DRM2.

Since it's an exception, this should be carefully considered when
tracking infelicities. The DRM2 code is not behaving as the rest of the
tribe...

                    THE 32 bits COMPATIBILITY

The other problematic part is the compatibility. In

./sys/compat/netbsd32/netbsd32_ioctl.c

the call to netbsd32_drm_ioctl() is in fact compiled out (the macro
is not defined), but I don't understand the condition of the (compiled
out) code:

1733:		if (IOCGROUP(com) == 'd') {

The call is not made, but is this really an indication of a DRM
related ioctl?

Furthermore, since the code is compiled out, "something else" is called
by default. Are we sure that these defaults can handle whatever DRM
related ioctl that could be passed?

                       CONCLUSION FOR NOW

It's no surprise that whatever version of DRM is causing problem: it's
convoluted around X11, that is showing its age; it's made to fit the
Linux kernel and trying to improve efficiency, and thus dealing a lot
with memory handling. But memory handling is, in fact, _the_ core of a
kernel.

If DRM* can be used, as long as volunteers are willing to tackle the
daunting task to tame it, we must do it so that it doesn't hamper the
NetBSD kernel; so that the kernel can still be without.

The size of the various versions of the DRM is huge, for the sources.
But for now, it is not a sine qua non for the kernel and it should stay
so.

There is, IMO, improvements to be made concerning the namespace: there
is historical fuzziness in the naming, and, if possible, this ought to
be fixed/improved.

I will modify further the userconf subroutines in order to allow to
disable simply, without the obligation to know all the devices
concerned, the drm related stuff. If the namespace can be fixed, what I
have done will be sufficient. If not, I will perhaps add
a /pattern/@/pattern/ to match a pattern or a child from a matching
parent; and/or add a '{NAME}' syntax, NAME being the name of a list
known by the userconf code. But it will be ad hoc, and will need
the lists to be set and modified when necessary.  Less elegant.

Further work will be done to try to provide a safe way to detect the
hardware, just to list resources to manage and capabilities, without
depending on the external code, in order to enable, if safe, the
modules afterwards.

I will also tackle the video/representation problem from the other end:
starting from the kernel. I have various notes and proposals to put
in documentation, and this message is already too long.

But just a closing note: As I have already seen, taking X11 as a
reference is not the way to do:  when dealing with monitors (see
one of the commits at the beginning of this message), one must go
back to the reference: the VESA DMT. X11 is not correct for everything
or not uptodate, at least for the version we have in source.  It's
just a basic mathematical principle: refer to the reference, not
to something indirect, if you don't want to drift.

HTH,
-- 
        Thierry Laronde <tlaronde +AT+ polynum +dot+ com>
                     http://www.kergis.com/
                    http://kertex.kergis.com/
Key fingerprint = 0FF7 E906 FBAF FE95 FD89  250D 52B1 AE95 6006 F40C


Home | Main Index | Thread Index | Old Index