Tag Archives: DRM

Splitting DRM and KMS device nodes

While most devices of the 3 major x86 desktop GPU-providers have GPU and display-controllers merged on a single card, recent development (especially on ARM) shows that rendering (via GPU) and mode-setting (via display-controller) are not necessarily bound to the same device. To better support such devices, several changes are being worked on for DRM.

In it’s current form, the DRM subsystem provides one general-purpose device-node for each registered DRM device: /dev/dri/card<num>. An additional control-node is also created, but it remains unused as of this writing. While in general a kernel driver is allowed to register multiple DRM devices for a single physical device, no driver made use of this, yet. That means, whatever hardware you use, both mode-setting and rendering is done via the same device node. This entails some rather serious consequences:

  1. Access-management to mode-setting and rendering is done via the same file-system node
  2. Mode-setting resources of a single card cannot be split among multiple graphics-servers
  3. Sharing display-controllers between cards is rather complicated

In the following sections, I want to look closer at each of these points and describe what has been done and what is still planned to overcome these restrictions. This is a highly technical description of the changes and serves as outline for the Linux-Plumbers session on this topic. I expect the reader to be familiar with DRM internals.

1) Render-nodes

While render-nodes have been discussed since 2009 on dri-devel, several mmap-related security-issues have prevented it from being merged. Those have all been fixed and 3-days ago, the basic render-node infrastructure has been merged. While it’s still marked as experimental and hidden behind the drm.rnodes module parameter, I’m confident we will enable it by default in one of the next kernel releases.

What are render-nodes?

From a user-space perspective, render-nodes are “like a big FPU” (krh) that can be used by applications to speed up computations and rendering. They are accessible via /dev/dri/renderD<num> and provide the basic DRM rendering interface. Compared to the old card<num> nodes, they lack some features:

  • No mode-setting (KMS) ioctls allowed
  • No insecure gem-flink allowed (use dma-buf instead!)
  • No DRM-auth required/supported
  • No legacy pre-KMS DRM-API supported

So whenever an application wants hardware-accelerated rendering, GPGPU access or offscreen-rendering, it no longer needs to ask a graphics-server (via DRI or wl_drm) but can instead open any available render node and start using it. Access-control to render-nodes is done via standard file-system modes. It’s no longer shared with mode-setting resources and thus can be provided for less-privileged applications.

It is important to note that render-nodes do not provide any new APIs. Instead, they just split a subset of the already available DRM-API off to a new device-node. The legacy node is not changed but kept for backwards-compatibility (and, obviously, for mode-setting).

It’s also important to know that render-nodes are not bound to a specific card. While internally it’s created by the same driver as the legacy node, user-space should never assume any connection between a render-node and a legacy/mode-setting node. Instead, if user-space requires hardware-acceleration, it should open any node and use it. For communication back to the graphics-server, dma-buf shall be used. Really! Questions like “how do I find the render-node for a given card?” don’t make any sense. Yes, driver-specific user-space can figure out whether and which render-node was created by which driver, but driver-unspecific user-space should never do that! Depending on your use-cases, either open any render-node you want (maybe allow an environment-variable to select it) or let the graphics-server do that for you and pass the FD via your graphics-API (X11, wayland, …).

So with render-nodes, kernel drivers can now provide an interface only for off-screen rendering and GPGPU work. Devices without any display-controller can avoid any mode-setting nodes and just provide a render-node. User-space, on the other hand, can finally use GPUs without requiring any privileged graphics-server running. They’re independent of the kernel-internal DRM-Master concept!

2) Mode-setting nodes

While splitting off render-nodes from the legacy node simplifies the situation for most applications, we didn’t simplify it for mode-setting applications. Currently, if a graphics-server wants to program a display-controller, it needs to be DRM-Master for the given card. It can acquire it via drmSetMaster() and drop it via drmDropMaster(). But only one application can be DRM-Master at a time. Moreover, only applications with CAP_SYS_ADMIN privileges can acquire DRM-Master. This prevents some quite fancy features:

  • Running an XServer without root-privileges
  • Using two different XServers to control two independent monitors/connectors of the same card

The initial idea (and Ilija Hadzic’s follow-up) to support this were mode-setting nodes. A privileged ioctl on the control-node would allow applications to split mode-setting resources across different device-nodes. You could have /dev/dri/modesetD1 and /dev/dri/modesetD2 to split your KMS CRTC and Connector resources. An XServer could use one of these nodes to program the now reduced set of resources. We would have one DRM-Master per node and we’d be fine. We could remove the CAP_SYS_ADMIN restriction and instead rely on file-system access-modes to control access to KMS resources.

Another discussed idea to avoid creating a bunch of file-system nodes, is to allocate these resources on-the-fly. All mode-setting-resources would now be bound to a DRM-Master object. An application can only access the resources available on the DRM-Master that it is assigned to. Initially, all resources are bound to the default DRM-Master as usual, which everyone gets assigned to when opening a legacy node. A new ioctl DRM_CLONE_MASTER is used to create a new DRM-Master with the same resources as the previous DRM-Master of an application. Via a DRM_DROP_MASTER_RESOURCE an application can drop KMS resources from their DRM-Master object. Due to their design, neither requires a CAP_SYS_ADMIN restriction as they only clone or drop privileges, they never acquire new privs! So they can be used by any application with access to the control node to create two new DRM-Master resources and pass them to two independent XServers. These use the passed FD to access the card, instead of opening the legacy or mode-setting nodes.

From the kernel side, the only thing that changes is that we can have multiple active DRM-Master objects. In fact, per DRM-Master one open-file might be allowed KMS access. However, this doesn’t require any driver-modifications (which were mostly “master-agnostic”, anyway) and only a few core DRM changes (except for vmwgfx-ttm-lock..).

3) DRM infrastructure

The previous two chapters focused on user-space APIs, but we also want the kernel-internal infrastructure to account for split hardware. However, fact is we already have anything we need. If some hardware exists without display-controller, you simply omit the DRIVER_MODESET flag and only set DRIVER_RENDER. DRM core will only create a render-node for this device then. If your hardware only provides a display-controller, but no real rendering hardware, you simply set DRIVER_MODESET but omit DRIVER_RENDER (which is what SimpleDRM is doing).

Yes, you currently get a bunch of unused DRM code compiled-in if you don’t use some features. However, this is not because DRM requires it, but only because no-one sent any patches for it, yet! DRM-core is driven by DRM-driver developers!

There is a reason why mid-layers are frowned upon in DRM land. There is no group of core DRM developers, but rather a bunch of driver-authors who write fancy driver-extensions. And once multiple drivers use them, they factor it out and move it to DRM core. So don’t complain about missing DRM features, but rather extend your drivers. If it’s a nice feature, you can count on it being incorporated into DRM-core at some point. It might be you doing most of the work, though!

DRM Render- and Modeset-Nodes

Another year, another Google Summer of Code. This time I got the chance to work on something that I had on my TODO list for quite a long time: DRM Render- and Modeset-Nodes

As part of the X.org Foundation mentoring organization, I will try to pick up the work from Ilija HadzicDave AirlieKristian HoegsbergMartin Peres and others. The idea is to extend the DRM user-space API of the linux kernel to split modeset and rendering interfaces apart. The main usage is to allow different access-modes for graphics-compositors (which require the modeset API) and client-side rendering or GPGPU-users (which both require the rendering API). We currently use the DRM-Master interface to restrict the modeset API to privileged applications. However, this requires SYS_CAP_ADMIN privileges, which is roughly equivalent to root-privileges. With two different interfaces for modeset and rendering APIs, we can apply a different set of filesystem-access-modes to each of them and thus get fine-grained access-control.

Apart from fine-grained access control, we also get some other nice features almost for free:

  • We will be able to run GPGPU clients without any running compositor or event without any display controller
  • We can split modeset objects across multiple nodes to allow multi-seat setups with a single display controller
  • Efficient compositor-stacking by granting page-flip access or full modeset access temporarily to sub-compositors

There are actually a lot of other ideas how to extend this. So I decided to concentrate on the modeset-node / render-node split first. Once that is done (and fully working), I will pick different ideas that depend on this and try to implement them. Considering the lot of work others have put in this already, I think if I get the split merged into mainline, the project will already be a great success. Everything on top of it will be some bonus that will probably take more time to get merged. But lets see, maybe it turns out to be easier than I think and we end up with some of the use-cases merged upstream, too.

Thanks to the X.org Foundation, Google and my GSoC-mentor Dave Airlie for giving me the chance to work on the DRM API! I hope it will be a productive summer.

GSoC-Proposal

If someone is interested in more details, some excerpts from my original GSoC proposal:

Project Description:
Since several years xserver is no longer the only user-space project that makes
use of the kernel DRM API. The introduction of KMS allowed many new projects to
emerge, including plymouth, weston and kmscon. On the other side, OpenCL support
allows applications to make use of DRM without requiring any KMS APIs. Even though
both use-cases work with the current APIs, there are a lot of restrictions that
need to be worked around.

The most problematic concept is DRM-Master. KMS applications are required to be
DRM-Master to perform modesetting, but DRM-Master is tightly coupled to
CAP_SYS_ADMIN/root. On the other side, render clients are required to be assigned
to a DRM-Master so they can get authenticated. This prevents off-screen/offline
rendering without a running compositor.

One possible solution is to split render- and modeset-nodes apart. The DRM control
node can be used as the management node (which is, as far as I understand, what
it was designed for, anyway). A separate static render-node is created for each
DRM device which is restricted to ioctls specific to rendering operations. Instead
of requiring drmAuth() for authorization, we can now use filesystem access-modes.
This allows slightly more dynamic access-control, but the biggest advantage is
that we can do off-screen/offline rendering without a running
compositor/DRM-Master.

On the other side, a modeset-node is a concept to have KMS separated from DRM.
The use-case is to split modeset objects (eg., crtcs, encoders, connectors) across
different modesetting applications. This allows one compositor to use one
CRTC+connector combination, while another compositor (maybe on another seat) can
use another CRTC+external-connector. This doesn't have to be a static setup. On
the contrary, one use-case I am very interested in is a dynamic modeset-object
assignment to temporary clients. This way, a fullscreen application can be granted
page-flip rights from the compositor to avoid context-switches to the compositor
for doing trivial page-flips only.

Deliverables
* Working render-node clients: Preferably an offline OpenCL example and
  a wayland EGL client
* Merged kernel render-node implementation with at least i915 support
* Dynamic kernel modeset-nodes
* "Zero-context-switches" wayland/weston fullscreen client (optional)

Known Problems:
There were several attempts to push render-nodes into the kernel, but all failed
due to missing motivation to finish the user-space clients. Writing up new fancy
APIs is one part, but pushing API changes to such big projects requires the whole
environment to work well with the changes. That's why I want to concentrate on
the user-space side of render-nodes. And I want to finish the render-nodes project
before continuing with modeset-nodes. The idea has been around long enough that
it's time that we get it done.

However, one problem is that I never worked with the low-level X11 stack. The
wayland environment is great for experiments and quite active. I am very familiar
with it and know how to get examples easily running. The xserver, however, is a
huge black box to me. I know the concepts and understand the input and graphics
drivers design. But I never read xserver core code. That's something I'd like to
change during this project. I will probably be limited to DRI and graphics
drivers, but that's a good start.

Another idea that came up quite often is something like gem-fs. It's far beyond
the scope of this project, but it's something I'd like to keep in mind when
designing the API. It's hard to account for something that's only an idea, but
the concepts seem related so I will try to understand the reasons behind gem-fs
and avoid orthogonal implementations.

A few smaller implementation-specific problems are already known, including the
mmap-security problem, static "possible_encoders"/"possible_crtcs" bitsets and
missing MMUs on GPUs. However, there already have been ideas how to solve them
so I don't consider them blockers for render-nodes.

Advanced DRM Mode-Setting API

I recently wrote a short How-To that introduces the linux DRM Mode-Setting API. It didn’t use any advanced techniques but I got several responses that it is a great introduction if you want to get started with linux DRM Mode-Setting. So I decided to go further and extend the examples to use double-buffering and vsync’ed page-flips.

The first extension that I wrote can be found here:

https://github.com/dvdhrm/docs/blob/master/drm-howto/modeset-double-buffered.c

It extends the old example to use two buffers so we no longer render into the front-buffer. It reduces a lot of tearing that you get when using the single-buffered example. However, it is still not perfect as you might swap the front and back buffer during a scanout-period and the display-controller will use the new buffer in the middle of the screen. So I extended this further to do the page-flip during a vertical-blank period using drmModePageFlip(). You can find this example here:

https://github.com/dvdhrm/docs/blob/master/drm-howto/modeset-vsync.c

This example also shows how to wait for page-flip events and integrate it into any select(), poll() or epoll based event-loop. Everything regarding page-flip-timing beyond that point depends on the use-cases and can get very hard to get right. I recommend reading Owen Taylor’s posts #1 and #2 on frame-timing for compositors.

There are still many more things like “DRM hardware-accelerated rendering”, “DRM planes/overlays/sprites”, “DRM flink/dmabuf buffer-passing” that I want to write How-Tos for. But time is short around Christmas so that’ll have to wait until next year.

Feedback is always welcome and you can find my email address in all the examples. Happy reading!

KMSCON Introduction

KMSCON is a KMS/DRM-based system console with an integrated terminal emulator. It was designed to replace the linux-kernel-console and virtual terminals (VTs). When run in default-mode, KMSCON allocates a virtual terminal and provides a terminal-emulator on it. It can thus be used as drop-in replacement for the linux-console and agetty. Compared to the linux-console, KMSCON provides a rich set of enhanced features including full-internationalized keyboard handling, full UTF8 input/font support, hardware-accelerated rendering, multi-seat support and more.

If run in listen-mode, KMSCON can also replace virtual terminals. This allows to run multiple graphics-servers (like kmscon, X-Server, Wayland Compositors) simultaneously on all seats not only on the default seat seat0.

Parts of this article expect the reader to be familiar with the term multi-seat. KMSCON runs on single-seat and multi-seat setups, but to understand the terms used here, you should read up on Wikipedia. On linux, the default seat is called seat0. This is also the primary seat for single-seat setups or if KMSCON is compiled without multi-seat support.

Default Mode

In default-mode KMSCON opens a virtual terminal (VT) to provide a terminal-emulator. It first checks whether the controlling terminal is a VT, if it’s not it tries to find an unused VT via VT_OPENQRY. You can also specify a VT on the command line via --vt=/dev/tty5, or –vt=tty5, or –vt=5. This syntax allows backwards compatibility to most getty implementations.

After startup the VT is automatically activated and switched to (this can be prevented with –no-switchvt). You can use the standard linux keyboard shortcuts ctrl+alt+F1 to ctrl+alt+F12 to switch between your VTs. KMSCON integrates seamlessly into existing setups and can be used in parallel with X-Servers, Wayland-Compositors or the linux-console. Only one VT is occupied by KMSCON, so you can still use the linux-console on all other VTs. But you can also run a KMSCON process on each VT replacing the linux-console everywhere.

By default, KMSCON spawns /bin/login on the new terminal session. You can change this with the –login option. However, for security reasons it is recommended to keep the default. If a session exits, it is automatically restarted. To terminate KMSCON send SIGTERM to the main process or use a daemon manager like systemd.

KMSCON tries to be backwards-compatible in terms of user-interaction to the linux-console. However, the internal terminal-emulator is developed to be compatible with xterm. This is because the linux-console‘s terminal-emulation layer is very limited and incompatible to many other terminal-emulators. On the other hand, xterm is the de-facto standard in terminal-emulation under linux and provides many enhanced control-sequences. Therefore, KMSCON tries to behave exactly like xterm does. This isn’t always as easy as it sounds so please file bug-reports if you encounter any incompatibilities.

With this knowledge we can now replace agetty. So instead of:

  /sbin/agetty --noclear tty5 38400 linux

we now run:

  /usr/bin/kmscon --vt=tty5 --no-switchvt

to replace the linux-console with KMSCON on VT-5.  KMSCON also ships optional systemd service files in ./kmscon/docs/*.service

Keyboard Input

KMSCON uses libxkbcommon for keyboard control. This library implements huge parts of the X11 Keyboard Specification without any dependencies to X11 source-code. It was developed to allow other applications than X-Server to provide internationalized keyboard handling. It recently saw its first release after several years of development but is currently not available in all major linux distributions. However, many distributions already provide experimental packages for it.

With XKB support on board, KMSCON can provide the same keyboard handling as the X-Server does. That is, keyboards are configured via the RMLVO options (Rules Model Layout Variant Options). The most commonly used option is probably –xkb-layout=<language> to change the keyboard layout. All other options are mostly unused.

Any keyboard setups that can be used with X11 can also be used with xkbcommon. Simply create your X11 keyboard layouts or use one of the many existing ones and configure KMSCON to use it.

Video Devices

KMSCON got its name from the linux kernel Direct Rendering Manager (DRM) subsystem (not to be confused with DRM: Digital Rights Management). DRM drivers provide a common set of APIs to perform Mode-Setting, called Kernel Mode-Setting (KMS). This is the API that is used by X-Server to program video output. KMSCON uses the same API and thus provides mostly the same compatibility to GPU drivers as X-Server does.

But KMSCON also supports linux fbdev devices for backwards-compatibility. In fact, the modular interface allows to provide drivers for all kinds of video hardware. However, it is recommended to write DRM drivers for your video-hardware instead of writing user-space drivers for KMSCON or X-Server. Because this allows all user-space programs to use the DRM API to access any type of video output device without extra user-space support for each driver.

Right from the beginning KMSCON provided multiple-GPU support. This means, KMSCON automatically picks up all connected GPUs and provides a system console on them. You can even hotplug new DisplayLink GPUs and KMSCON detects them during runtime and instantly provides a console on them. Unfortunately, GPU detection isn’t as straightforward as one would think. On some systems there are GPUs that shouldn’t be touched by KMSCON. That’s why KMSCON provides the –gpu switch to change the GPU selection algorithm. A GPU blacklist configuration file or option is also on its way.

On fbdev and dumb-DRM devices, KMSCON uses 2D rendering without any hardware acceleration. But if KMSCON is compiled with full DRM video backends, it can use mesa3D’s OpenGLESv2 implementation to provide hardware-accelerated rendering. Use –hwaccel to enable this during runtime. It can speed up rendering by multiple orders of magnitude. However, on older systems it might even slow down rendering. It is disabled by default and needs to be explicitly enabled with –hwaccel.

Seat Selection

By default, KMSCON runs on the seat that it was started on. At most times, this is the default seat seat0. However, you can run KMSCON on other seats with the –seats option. It takes a list of seat names that KMSCON will run on. Each seat is independent and you can either run one KMSCON process for each seat or you can even run a single KMSCON process on multiple seats. The latter will allow sharing of system-resources like font glyph-caches. However, if 3D-hardware-acceleration is enabled, unexpected latencies may occur in the DRM drivers and you shouldn’t share a single KMSCON process across multiple seats for decent user-experience.

On seat0 KMSCON can make use of VTs. However, on seats other than seat0 (or even on seat0 if VTs are disabled) linux does not provide VTs. Therefore, KMSCON has to run without them. This means, KMSCON will automatically activate itself and run unconditionally on this seat. Unfortunately this has the side-effect that no other graphics-server (like X-Server) can run on this seat. Without the synchronization API of VTs there is no way to dispatch the graphics/input devices between multiple graphics servers. Therefore, most users will prefer running an X-Server on those seats. However, if no X11 is needed, KMSCON runs perfectly fine on those seats, too.

Listen-Mode

In default-mode KMSCON runs only on seats that are available during startup and terminates after all seats it runs on are either gone or their controlling VT hung up. This is perfect for VTs on seat0 but it requires another process to start KMSCON for each new seat showing up.

In listen-mode KMSCON runs as daemon waiting for new seats to show up. It automatically spawns a new terminal session on each seat matching the –seats option. KMSCON will not exit until SIGTERM is caught. Note that KMSCON ignores seats with VTs (normally only seat0) in this mode as you should run KMSCON in default-mode on those seats.

VT Replacement

The linux-kernel-console and VTs are tightly bound to each other. There is only one kernel configuration option to control them both: CONFIG_VT. KMSCON can already replace the linux-kernel-console but to disable CONFIG_VT, we also need a proper replacement for virtual terminals. As previously noted, KMSCON can run smoothly without VTs, however, this means that you can only run a single graphics-server on a seat and most users will probably choose X-Server here (and I would do so, too).

Fortunately, KMSCON already provides a solution to this. The –cdev-session option provides fake VTs for all seats that do not have real VTs. This allows to run X-Server, KMSCON, a Wayland Compositor and any other graphics-server simultaneously without changing a single line of code. However, this is beyond the scope of this introduction. Stay tuned for a follow-up post that introduces KMSCON session support and cdev-sessions in more detail.

Current State

KMSCON works! No special setup, no special system requirements and no weird dependencies are needed. You can check out KMSCON on any major linux distribution. Right now. What you need is:

  • libxkbcommon: This library has no external dependencies and can easily be installed on any distribution. Many distributions even provide experimental packages for it. See xkbcommon.org.
  • libudev: Udev is used for hotplugging and device detection. Every major distribution provides it.
  • kmscon: You can get KMSCON from github.

Everything else is optional! For proper font-rendering you also need pango or freetype2. For DRM video output you need libdrm. For 3D-hardware-acceleration mesa3D is needed. For multi-seat support systemd-logind is used.

However, please note that KMSCON is still experimental. I do my best to keep backwards-compatibility and fix all bugs that are reported. But I am unable to test KMSCON on all imaginable setups. So please report all bugs to github.com/dvdhrm/kmscon and I promise to have a look at it.

Furthermore, the TODO list grows steadily and I still have lots of ideas how to improve KMSCON. New ideas are very welcome, but please bear with me if it takes more time than expected to implement them. There is probably lots of stuff with higher priority on my list. But patches are highly appreciated even if they implement low-priority features.

There is a man-page kmscon(1) that explains many concepts and command-line arguments right-away. But do not hesitate to contact me personally if you have any questions about KMSCON. And for all developers I am doing a presentation about deprecating CONFIG_VT and KMSCON during FOSDEM-13 in Brussels next year. Hope to see you there!

Linux DRM Mode-Setting API

The Direct Rendering Manager (DRM) is a subsystem of the linux kernel that manages access to graphics cards (GPUs). It is the main video API used by X.org‘s xserver and the xf86-video-* video drivers. However, it can also be used by independent programs to program video output without using the xserver or wayland. In the past most other projects used the much older fbdev API, however, with more and more drivers being added to the DRM subsystem, there is really no reason to avoid DRM on modern computers, anymore. Unfortunately, there hasn’t been any documentation of the DRM API, yet.

DRM-Modesetting HowTo

I have written a short introduction into the DRM mode-setting API, which can be found on github. It is a full C-file with detailed comments on what is needed to perform simple mode-setting with the DRM-API. I embedded the documentation directly into the source file as this makes reading a lot more convenient:

https://github.com/dvdhrm/docs/blob/master/drm-howto/modeset.c

This document does not describe the whole DRM API. There are parts like the OpenGL-rendering-pipeline, which are driver-dependent and which should almost never be accessed outside of the mesa-3D implementation. Instead, this document describes the API which is needed to write simple applications performing software-rendering similar to fbdev but with the DRM API.

Furthermore, this document is not free of errors. So please contact me if something is wrong, if essential parts are missing or if you intend to extend this documentation.

More tutorials will follow, including “DRM double/triple-buffering”, “DRM vsync’ed pageflips”, “DRM hardware-accelerated rendering”, “DRM planes/overlays/sprites” and more.

I hope you enjoy this short introduction.

Edit: For a new series of How-To’s, see http://dvdhrm.wordpress.com/2012/12/21/advanced-drm-mode-setting-api/

KMSCON: Linux KMS/DRM based Virtual Console

For about half a year I am now constantly working on a new project called kmscon. The idea emerged when reading on Jesse Barnes’ Blog about EGL+KMS. KMS stands for Kernel Mode Setting and is provided by the kernel DRM (Direct Rendering Manager) subsystem. The modesetting API (KMS) is a small part of the whole DRM API, but it works for all DRM drivers in the kernel. Therefore, with DRM you can get simple framebuffer access to all connected monitors. With udev you will also be notified about hot-plugged monitors. Perfect conditions for kmscon.

Kmscon is a small application that simply draws a VT220/VT102 compatible terminal emulator on all connected displays. A simple replacement for the kernel-console or for xterm. It is fully hot-plug capable and automatically detects all connected displays. It is multi-seat capable and only selects monitors that are assigned to the correct seat. It has only one mandatory dependency, which is libudev. This is used for device enumeration and hotplugging. All other dependencies are optional.

Main focus was not writing a decent VT220 emulator. There are lots of them out there (the guys from the Enlightenment project wrote one in under 1 month called terminology) and you can either include an existing one with kmscon or improve the kmscon vte layer. I rather focused on the integration with the operating system. kmscon runs without an X11 environment or any helpers. It needs to do everything on its own. No Gtk, no EFL, no Qt. Of course, they could be included and in fact, kmscon includes optional pango-font-renderers, however, at such a low level, you want at least the possibility to run kmscon without any of these dependencies. Therefore, bare kmscon uses a built-in static 8×16 font which is copied into the 2D framebuffers to draw a console.

Hardware-accelerated Rendering

If mesa is compiled with –with-egl-platforms=drm (which it is on all major distributions except Arch Linux) then we can get OpenGL contexts on bare DRM devices. This is done via EGL. kmscon includes an optional rendering backend for it when compiled with –enable-gles2. In combination with the Pango or Freetype2 font backends of kmscon, you get a hardware-accelerated console with anti-aliases fonts without any X11/Wayland/etc.

If you think this is overkill or if you have no idea why this is needed, then try running a console on a slower machine like the Intel Atom N450 or some Pentium III. Then use an application like “less” and scroll one screen at a time. This means, the whole console is redrawn on every keyboard input. My Atom N450 is fast enough to draw this but if I connect a second monitor, then this will get horribly slow very fast. Rendering both monitors takes about half a second here. When connecting 5 monitors via DisplayLink USB-devices, the performance will be horrible. Therefore, I am happy about every CPU-cycle I can safe by pushing rendering to the graphics-card.

The Use-Cases

I got much (often quite harsh) feedback that kmscon is again some software that is not needed as it replaces perfectly well-working software. Therefore, I want to explain what kmscon does better and why I need it. I compare it to the linux kernel-console as kmscon is a replacement for it:

  • Full internationalization support. No-one wants (and we currently do not have) full internationalized keyboard handling in the kernel. There is also no way to print a full CJK character set or even the full Unicode character set on the linux console. Adding this to the kernel would mean having big character tables in non-swappable kernel memory. Therefore, implementing this in user-space is the only way.
  • Hardware accelerated drawing. With multi-seat becoming more and more common and multiple monitors connected to a single computer, we do not want to spend too much time drawing text on the CPU. However, using the GPU pipeline from the kernel would require new in-kernel DRM APIs which are currently not available. With GPU-accelerated rendering we can also add anti-aliased fonts or soft-shadows which can enhance readability a lot (although others might consider this cosmetic BS).
  • Controllable Monitor/Console mapping. By using the DRM API we can have as many consoles simultaneously as we want and can map them to different monitors or clone the output. We can even span a console across multiple monitors. I also think of some kind of “tabbed” consoles.
  • Full vt220 to vt510 support. The kernel console supports only a small subset of the DEC VT APIs. It does not even correctly emulate the VT102 API (although it’s pretty close to vt102). In user-space we can extend this to even support all the xterm supported escape sequences. This also includes a better scrollback-buffer which is pretty limited in the kernel console.
  • No CONFIG_VT. CONFIG_VT is the kernel config-option that enables the virtual-consoles. The reasons why I think it is bad are beyond the scope of this document, but kmscon was mainly designed to also work without VTs, that is, CONFIG_VT=n.

There are many more points, but these 5 points were important enough for me to start working on a replacement. However, I never tried making kmscon the main working console for your graphical environment. On the contrary, I personally still use xterm for my daily work, but as an emergency console I use kmscon. It works when everything else has failed and always provides me a safe fallback-console.

Furthermore, kmscon works perfectly well simultaneously with the kernel-console. So if you don’t like kmscon, then don’t use it. But if you want to give it a shot, you can use it in parallel with other VTs.

“The console belongs in the kernel so it can run under memory pressure and/or during system failure!

I get this a lot. As a matter of fact the in-kernel linux console does not run under memory-pressure or during system failure, either. Therefore, there is almost no disadvantage in running the console in user-space. In fact, the kernel console and kmscon only implement the rendering pipeline for the text console. Anything you do with it or any program that you run on the console (including a shell like bash) runs in user-space! And when the system fails and user-space is no longer working correctly, then your bash won’t run either so there is no point in having a working console layer when there is nothing to show.

And even if your video-driver fails, then your kernel-console cannot recover as you probably run fbcon which uses the same drivers as user-space. The only fallback would be vgacon which is only accessible from the kernel, but recovering via text-mode doesn’t work in most video-driver-failure-cases either. Therefore, this whole argument is simply wrong, but most of you probably know that already.

However, one needs to take into account that the kernel-console can also print kernel-panics/oopses. This cannot be done by kmscon or any replacement. But this feature does not require a terminal-emulator nor VTs so I wrote a replacement for this called fblog. This is in fact a very useful and prominent feature of the kernel-console which must remain in the kernel.

Kmscon facts

The current kmscon release is kmscon-3 which is still a development release. However, it works quite well on my machine and I would be glad to get some more testers. You can get more information on:

Kmscon has many features. Here is a list of the most important ones:

  1. Safe fallback rendering via /dev/fbX (simply run ./kmscon –fbdev)
  2. DRM dumb-fbs as 2D backend
  3. EGL+3D hardware-accelerated rendering when compiled with OpenGLESv2
  4. Full hotplug capable (monitors and input devices)
  5. Multi-seat capable
  6. Support for multiple monitors
  7. Almost full VT220 compatibility
  8. Modularized input/video/VT handling via libuterm
  9. Only libudev.so as mandatory dependency!
  10. Plain built-in optional keyboard backend
  11. Optional internationalized keyboard backend based on libxkbcommon.so
  12. Built-in VT-compatibility but also runs without VTs
  13. Fully Unicode/UTF8 compatible
  14. Fully internationalized terminal emulation
  15. …and more…

If you want to run kmscon, then please run it as root as it needs access to graphics hardware. By default, kmscon uses DRM devices as output devices. It does not use fbdev devices as many DRM devices also provide fbdev devices for the same physical monitor. If you pass “–fbdev” as command-line argument, then kmscon uses fbdev exclusively! kmscon also supports using DRM devices without OpenGL/EGL/etc.! If compiled kmscon without OpenGLESv2 support but with DRM support, then the DRM devices are used to get direct framebuffer access similar to fbdev. Only if OpenGLESv2 is enabled, kmscon uses hardware-acceleration.

Run “./kmscon -h” to get more information on command-line options. The “–debug” switch is very helpful and “–xkb-layout=de” will switch to a German keyboard layout (if you use the xkbcommon keyboard backend).

Kmscon is still experimental, but I would be glad about any feedback.