[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 <tlaro...@polynum.com> 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 <tlaro...@polynum.com> 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 <tlaro...@polynum.com> 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