<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Maíra Canal</title>
        <description>Blogging about graphics development whenever I can</description>
        <link>https://mairacanal.github.io</link>
        <atom:link href="https://mairacanal.github.io/atom.xml" rel="self" type="application/rss+xml" />
        <lastBuildDate>Mon, 28 Oct 2024 12:00:00 +0000</lastBuildDate>
        
            <item>
                <title>Unleashing Power: Enabling Super Pages on the RPi</title>
                
                <description>&lt;p&gt;Unleashing the power of 3D graphics in the Raspberry Pi is a key commitment for
&lt;a href=&quot;https://www.igalia.com&quot;&gt;Igalia&lt;/a&gt; through its collaboration with &lt;a href=&quot;https://www.raspberrypi.com&quot;&gt;Raspberry
Pi&lt;/a&gt;. The introduction of Super Pages for the
Raspberry Pi 4 and 5 marks another step in this journey, offering some
performance enhancements and more efficient memory usage. In this post, we’ll
dive deep into the technical details of Super Pages, discuss the challenges we
faced during implementation, and illustrate the benefits this feature brings to
the Raspberry Pi ecosystem.&lt;/p&gt;

&lt;h2 id=&quot;what-are-super-pages&quot;&gt;What are Super Pages?&lt;/h2&gt;

&lt;p&gt;A Memory Management Unit (MMU) is a hardware component responsible for handling
memory access at the system level. It translates virtual addresses used by
programs into physical addresses in main memory, enabling efficient memory
management and protection. The MMU allows the operating system to allocate
memory dynamically, isolating processes from one another to prevent them from
interfering with each other’s memory.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Recommendation:&lt;/strong&gt; 📚 &lt;em&gt;Structured computer organization&lt;/em&gt; by Andrew Tanenbaum&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The V3D MMU, which is part of the Broadcom GPU found in the Raspberry Pi 4 and
5, is responsible for translating 32-bit virtual addresses (VA) used by V3D into
40-bit physical addresses used externally to V3D. The MMU relies on a page
table, stored in physical memory, which maps virtual addresses to their
corresponding physical addresses. The operating system manages this page table,
and the MMU uses it to perform address translation during memory access.&lt;/p&gt;

&lt;p&gt;A fundamental principle of modern operating systems is that memory is not stored
contiguously. Instead, a contiguous block of memory is divided into smaller
blocks, called “pages”, which are scattered across the entire address space.
These pages are typically 4KB in size. This approach enables more efficient
memory management and allows for features like virtual memory and memory
protection.&lt;/p&gt;

&lt;p&gt;Over the years, the amount of available memory in computers has increased
dramatically. An early IBM PC had up to 640 KiB of RAM, whereas the ThinkPad I’m
typing on right now has 32 GB of RAM. Naturally, memory demands have grown
alongside this increase. Today, it’s common for web browsers to consume several
gigabytes of RAM, and a single shader can take up multiple megabytes.&lt;/p&gt;

&lt;p&gt;As memory usage grows, a 4KB page size may become inefficient for managing large
memory blocks. Handling a large number of small pages for a single block means
the MMU must perform multiple address translations, which increases overhead.
This can reduce the effectiveness of the Translation Lookaside Buffer (TLB), as
it must store and handle more entries, potentially leading to more cache misses
and reduced overall performance.&lt;/p&gt;

&lt;p&gt;This is why many CPU manufacturers have introduced support for larger page
sizes. For instance, x86 CPUs typically support 4KB and 2MB pages, with 1GB
pages available if supported by the hardware. Similarly, ARM64 CPUs can support
4KB, 16KB, and 64KB page sizes. These larger page sizes help reduce the number
of pages the MMU needs to manage, improving performance by reducing the overhead
of address translation and making more efficient use of the TLB.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So, if CPUs are using bigger sizes, why shouldn’t GPUs do the same?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;By default, V3D supports 4KB pages. However, by setting specific bits in the
page table entry, it is possible to create 64KB “Big Pages” and 1MB “Super
Pages.” The issue is that the current V3D driver available in Linux does not
enable the use of Big or Super Pages, meaning this hardware feature is currently
unused.&lt;/p&gt;

&lt;p&gt;The advantage of enabling Big and Super Pages is that once an entry for any page
within a Big or Super Page is cached in the MMU, it can be used to translate all
virtual addresses within that page’s range without needing to fetch additional
entries. In theory, this should result in improved performance, especially for
applications with high memory demands, such as those using multiple large buffer
objects (BOs).&lt;/p&gt;

&lt;p&gt;As Igalia continually strives to enhance the experience for Raspberry Pi users,
we decided to implement this feature in the upstream kernel. But before diving
into the implementation details, let’s take a look at the real-world results and
see if the theoretical benefits of Super Pages have translated into measurable
improvements for Raspberry Pi users.&lt;/p&gt;

&lt;h2 id=&quot;what-does-this-feature-mean-for-rpi-users&quot;&gt;What Does This Feature Mean for RPi Users?&lt;/h2&gt;

&lt;p&gt;With Super Pages implemented, let’s now explore the actual performance
improvements observed on the Raspberry Pi and see how impactful this feature is
for users.&lt;/p&gt;

&lt;h3 id=&quot;benchmarking-super-pages-traces-and-fps-improvements&quot;&gt;Benchmarking Super Pages: Traces and FPS Improvements&lt;/h3&gt;

&lt;p&gt;To measure the impact of Super Pages, we tested a variety of games and demos
traces on the Raspberry Pi 4 and 5, covering genres from action to racing. On
average, we observed a +1.40% FPS improvement on the Raspberry Pi 4 and a +1.30%
improvement on the Raspberry Pi 5.&lt;/p&gt;

&lt;p&gt;For instance, on the Raspberry Pi 4, &lt;em&gt;Warzone 2100&lt;/em&gt; saw an 8.36% FPS increase,
and on the Raspberry Pi 5, &lt;em&gt;Quake II&lt;/em&gt; enjoyed a 3.62% boost. These examples
demonstrate the benefits of Super Pages in resource-demanding applications,
where optimized memory handling becomes critical.&lt;/p&gt;

&lt;h4 id=&quot;raspberry-pi-4-fps-improvements&quot;&gt;Raspberry Pi 4 FPS Improvements&lt;/h4&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Trace&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Before Super Pages&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;After Super Pages&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Improvement&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;warzone2100.30secs.1024x768.trace&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;56.39&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;61.10&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+8.36%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;ue4_shooter_game_shooting_low_quality_640x480.gfxr&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;20.71&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;21.47&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+3.65%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;quake3e_capture_frames_1800_through_2400_1920x1080.gfxr&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;60.88&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;62.50&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+2.67%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;supertuxkart-menus_1024x768.trace&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;112.62&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;115.61&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+2.65%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;ue4_shooter_game_shooting_high_quality_640x480.gfxr&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;20.45&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;20.88&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+2.10%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;quake2-gles3-1280x720.trace&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;59.76&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;60.84&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+1.82%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;ue4_sun_temple_640x480.gfxr&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;27.60&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;28.03&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+1.54%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;vkQuake_capture_frames_1_through_1200_1280x720.gfxr&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;54.59&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;55.30&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+1.29%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;ue4_shooter_game_low_quality_640x480.gfxr&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;32.75&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;33.08&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+1.00%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;sponza_demo02_800x600.gfxr&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;20.90&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;21.03&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+0.61%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;supertuxkart-racing_1024x768.trace&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;8.58&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;8.63&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+0.60%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;ue4_shooter_game_high_quality_640x480.gfxr&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;19.62&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;19.74&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+0.59%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;serious_sam_trace02_1280x720.gfxr&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;44.00&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;44.21&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+0.50%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;ue4_vehicle_game-2_640x480.gfxr&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;12.59&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;12.65&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+0.49%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;sponza_demo01_800x600.gfxr&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;21.42&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;21.46&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+0.19%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;quake3e-1280x720.trace&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;84.45&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;84.52&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+0.09%&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h4 id=&quot;raspberry-pi-5-fps-improvements&quot;&gt;Raspberry Pi 5 FPS Improvements&lt;/h4&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Trace&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Before Super Pages&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;After Super Pages&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Improvement&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;quake2-gles3-1280x720.trace&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;151.77&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;157.26&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+3.62%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;supertuxkart-menus_1024x768.trace&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;306.79&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;313.88&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+2.31%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;warzone2100.30secs.1024x768.trace&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;140.92&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;144.03&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+2.21%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;vkQuake_capture_frames_1_through_1200_1280x720.gfxr&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;131.45&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;134.20&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+2.10%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;ue4_vehicle_game-2_640x480.gfxr&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;24.42&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;24.88&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+1.89%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;ue4_shooter_game_high_quality_640x480.gfxr&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;32.12&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;32.53&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+1.29%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;ue4_sun_temple_640x480.gfxr&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;42.05&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;42.55&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+1.20%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;ue4_shooter_game_shooting_high_quality_640x480.gfxr&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;52.77&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;53.31&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+1.04%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;quake3e-1280x720.trace&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;238.31&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;240.53&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+0.93%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;warzone2100.70secs.1024x768.trace&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;151.09&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;151.81&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+0.48%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;sponza_demo02_800x600.gfxr&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;50.81&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;51.05&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+0.46%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;supertuxkart-racing_1024x768.trace&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;20.91&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;20.98&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+0.33%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;ue4_shooter_game_low_quality_640x480.gfxr&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;59.68&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;59.86&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+0.29%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;quake3e_capture_frames_1_through_1800_1920x1080.gfxr&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;167.70&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;168.17&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+0.29%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;ue4_shooter_game_shooting_low_quality_640x480.gfxr&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;53.40&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;53.51&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+0.22%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;quake3e_capture_frames_1800_through_2400_1920x1080.gfxr&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;163.37&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;163.64&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+0.17%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;serious_sam_trace02_1280x720.gfxr&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;60.00&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;60.03&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+0.06%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;sponza_demo01_800x600.gfxr&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;45.04&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;45.04&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&amp;lt;.01%&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;While an average +1% FPS improvement might seem modest, Super Pages can deliver
more noticeable gains in memory-intensive 3D applications and when the GPU is
under heavy usage. Let’s see how the Super Pages perform on Mesa CI.&lt;/p&gt;

&lt;h3 id=&quot;benchmarking-super-pages-mesa-ci-job-duration&quot;&gt;Benchmarking Super Pages: Mesa CI Job Duration&lt;/h3&gt;

&lt;p&gt;To avoid introducing regressions in user-space, I usually test my custom kernels
with Mesa CI, focusing on the “broadcom-postmerge” stage to verify that all
Piglit and CTS tests ran smoothly. For Super Pages, I was pleasantly surprised
by the job duration results, as some job durations were reduced by several
minutes.&lt;/p&gt;

&lt;h4 id=&quot;mesa-ci-jobs-duration-improvements&quot;&gt;Mesa CI Jobs Duration Improvements&lt;/h4&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Job&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Before Super Pages&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;After Super Pages&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;v3d-rpi4-traces:arm64&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;~4m30s&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;~3m40s&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;v3d-rpi5-traces:arm64&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;~3m30s&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;~2m45s&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;v3d-rpi4-gl-full:arm64 */6&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;~24-25 minutes&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;~22-23 minutes&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;v3d-rpi5-gl-full:arm64&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;~48 minutes&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;~48 minutes&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;v3dv-rpi4-vk-full:arm64 */6&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;~44 minutes&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;~41 minutes&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;v3dv-rpi5-vk-full:arm64&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;~102 minutes&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;~92 minutes&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Seeing these reductions is especially rewarding. For example, the
“v3dv-rpi5-vk-full:arm64” job duration decreased by 10 minutes, meaning more FPS
for users and shorter wait times for Mesa developers.&lt;/p&gt;

&lt;h3 id=&quot;benchmarking-super-pages-ps2-emulation&quot;&gt;Benchmarking Super Pages: PS2 Emulation&lt;/h3&gt;

&lt;p&gt;After sharing a couple of tables, I’ll admit that showcasing performance
improvements solely through numbers doesn’t always convey the real impact.
Personally, I find it more satisfying to see performance gains in action with
real-world applications.&lt;/p&gt;

&lt;p&gt;This led me to explore PlayStation 2 (PS2) emulation on the RPi 5. From watching
YouTube videos, I noticed that PS2 is a popular console for the RPi 5. While the
PlayStation (PS1) emulates well even on the RPi 4, and Nintendo 64 and Sega
Saturn struggle across most hardware, PS2 hits a sweet spot for testing the RPi
5’s limits.&lt;/p&gt;

&lt;p&gt;Fortunately, I still have my childhood PS2 — my second console after the
Nintendo GameCube, and one of the most successful consoles worldwide, including
in Brazil. With a library packed with titles like &lt;em&gt;Metal Gear Solid&lt;/em&gt;, &lt;em&gt;Resident
Evil&lt;/em&gt;, &lt;em&gt;Tomb Raider&lt;/em&gt;, and &lt;em&gt;Shadow of the Colossus&lt;/em&gt;, the PS2 remains a great
system for collectors and retro gamers alike.&lt;/p&gt;

&lt;p&gt;I selected a few games from my collection to benchmark on the RPi 5 using a PS2
emulator. My emulator of choice was &lt;a href=&quot;https://github.com/AetherSX2-backup/AetherSX2-builds&quot;&gt;Aether
SX2&lt;/a&gt; with Vulkan support.
Although AetherSX2 is no longer in development, it still performs well on the
RPi.&lt;/p&gt;

&lt;p&gt;Initially, many games were barely playable, especially those with large buffer
objects, like Shadow of the Colossus and Gran Turismo 4. However, after enabling
Super Pages support, I noticed immediate improvements. For example, Shadow of
the Colossus wouldn’t even open before Super Pages, and while it’s not fully
playable yet, it does load now. This isn’t a silver bullet, but it’s a step
forward in improving the driver one piece at a time.&lt;/p&gt;

&lt;p&gt;I ended up selecting four games for a video comparison: &lt;em&gt;Burnout 3: Takedown&lt;/em&gt;,
&lt;em&gt;Metal Gear Solid 3: Snake Eater&lt;/em&gt;, &lt;em&gt;Resident Evil 4&lt;/em&gt;, and &lt;em&gt;Tekken 4&lt;/em&gt;.&lt;/p&gt;

&lt;video width=&quot;100%&quot; controls=&quot;&quot;&gt;
  &lt;source src=&quot;/assets/videos/super-pages-rpi5-2024.mp4&quot; type=&quot;video/mp4&quot; /&gt;
  Your browser does not support the video tag.
&lt;/video&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; The BIOS used in the emulator was extracted from my own PS2,
and I played only games I own, with ROMs I personally extracted. Neither I nor
Igalia encourage using downloaded BIOS or ROM files from the internet.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;From the video, we can see noticeable improvements in all four games. Although
they aren’t perfectly playable yet, the performance gains are evident,
particularly in &lt;em&gt;Resident Evil 4&lt;/em&gt;, where the gameplay saw a solid 5 FPS boost. I
realize 18 FPS might not satisfy most players, but I still had a lot of fun
playing &lt;em&gt;Resident Evil 4&lt;/em&gt; on the RPi 5.&lt;/p&gt;

&lt;p&gt;When tracking the FPS for these games, it’s clear that the performance gains go
well beyond the average 1% seen in other benchmarks. Super Pages show their true
potential in high-memory applications like PS2 emulation.&lt;/p&gt;

&lt;p&gt;Having seen the performance gains Super Pages can bring to the Raspberry Pi,
let’s now dive into the technical aspects of the feature.&lt;/p&gt;

&lt;h2 id=&quot;implementing-super-pages&quot;&gt;Implementing Super Pages&lt;/h2&gt;

&lt;p&gt;The first challenge was figuring out how to allocate a contiguous block of
memory using &lt;em&gt;shmem&lt;/em&gt;. The Shared Memory Virtual Filesystem (&lt;em&gt;shmem&lt;/em&gt;) is used as
a flexible memory mechanism that allows the GPU and CPU to share access to BOs
through the system’s temporary filesystem, &lt;em&gt;tmpfs&lt;/em&gt;. &lt;em&gt;tmpfs&lt;/em&gt; is a volatile
filesystem that stores files in RAM, making it ideal for temporary or high-speed
data that doesn’t need to persist on RAM.&lt;/p&gt;

&lt;p&gt;For example, to allocate a 256KB BO across four 64KB pages, we need four
contiguous 64KB memory blocks. However, by default, &lt;em&gt;tmpfs&lt;/em&gt; only allocates
memory in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PAGE_SIZE&lt;/code&gt; chunks (as seen in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shmem_file_setup()&lt;/code&gt;), whereas
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PAGE_SIZE&lt;/code&gt; is 4KB on the Raspberry Pi 4 and 16KB on the Raspberry Pi 5. Since
the function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drm_gem_object_init()&lt;/code&gt; — which initializes an allocated
shmem-backed GEM object — relies on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shmem_file_setup()&lt;/code&gt; to back these objects
in memory, we had to consider alternatives, as the default &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PAGE_SIZE&lt;/code&gt; would
divide memory into increments that are too small to ensure the large, contiguous
blocks needed by the GPU.&lt;/p&gt;

&lt;p&gt;The solution we proposed was to create &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drm_gem_object_init_with_mnt()&lt;/code&gt;, which
allows us to specify the &lt;em&gt;tmpfs&lt;/em&gt; mountpoint where the GEM object will be
created. This enables us to allocate our BOs in a mountpoint that supports
larger page sizes. Additionally, to ensure that our BOs are allocated in the
correct mountpoint, we introduced &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drm_gem_shmem_create_with_mnt()&lt;/code&gt;, which
allows the mountpoint to be specified when creating a new DRM GEM shmem object.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://lore.kernel.org/dri-devel/20240923141348.2422499-5-mcanal@igalia.com/&quot;&gt;[PATCH v6 04/11] drm/gem: Create a drm_gem_object_init_with_mnt() function&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://lore.kernel.org/dri-devel/20240923141348.2422499-7-mcanal@igalia.com/&quot;&gt;[PATCH v6 06/11] drm/gem: Create shmem GEM object in a given mountpoint&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The next challenge was figuring out how to create a new mountpoint that would
allow for different page sizes based on the allocation. Simply creating a new
&lt;em&gt;tmpfs&lt;/em&gt; mountpoint with a fixed bigger page size wouldn’t suffice, as we needed
flexibility for various allocations. Inspired by the i915 driver, we decided to
use a &lt;em&gt;tmpfs&lt;/em&gt; mountpoint with the “huge=within_size” flag. This flag, which
requires the kernel to be configured with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CONFIG_TRANSPARENT_HUGEPAGE&lt;/code&gt;, enables
the allocation of huge pages.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://docs.kernel.org/admin-guide/mm/transhuge.html&quot;&gt;Transparent Huge Pages
(THP)&lt;/a&gt; is a kernel
feature that automatically manages large memory pages to improve performance
without needing changes from applications. THP dynamically combines smaller
pages into larger ones, typically 2MB, reducing memory management overhead and
improving cache efficiency.&lt;/p&gt;

&lt;p&gt;To support our new allocation strategy, we created a dedicated &lt;em&gt;tmpfs&lt;/em&gt;
mountpoint for V3D, called gemfs, which provides us an ideal space for managing
these larger allocations.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://lore.kernel.org/dri-devel/20240923141348.2422499-6-mcanal@igalia.com/&quot;&gt;[PATCH v6 05/11] drm/v3d: Introduce gemfs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With everything in place for contiguous allocations, the next step was configuring V3D to enable Big/Super Page support.&lt;/p&gt;

&lt;p&gt;We began by addressing a major source of memory pressure on the Raspberry Pi:
the current 128KB alignment for allocations in the virtual memory space. This
alignment wastes space when handling small BO allocations, especially since the
userspace driver performs a large number of these small allocations.&lt;/p&gt;

&lt;p&gt;As a result, we can’t fully utilize the 4GB address space available for the GPU
on the Raspberry Pi 4 or 5. For example, we can currently allocate up to 32,000
BOs of 4KB (~140MB) and 3,000 BOs of 400KB (~1.3GB). This becomes a limitation
for memory-intensive applications. By reducing the page alignment to 4KB, we can
significantly increase the number of BOs, allowing up to 1,000,000 BOs of 4KB
(~4GB) and 10,000 BOs of 400KB (~4GB).&lt;/p&gt;

&lt;p&gt;Therefore, the first change I made was reducing the VA alignment of all
allocations to 4KB.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://lore.kernel.org/dri-devel/20240923141348.2422499-8-mcanal@igalia.com/&quot;&gt;[PATCH v6 07/11] drm/v3d: Reduce the alignment of the node allocation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the alignment issue resolved, we can now implement the code to properly set
the flags on the Page Table Entries (PTE) for Big/Super Pages. Setting these
flags is straightforward — a simple bitwise operation. The challenge lies in
determining which BOs can be allocated in Super Pages. For a BO to be eligible
for a Big Page, its virtual address must be aligned to 64KB, and the same
applies to its physical address. Same thing for Super Pages, but now the
addresses must be aligned to 1MB.&lt;/p&gt;

&lt;p&gt;If the BO qualifies for a Big/Super Page, we need to iterate over 16 4KB pages
(for Big Pages) or 256 4KB pages (for Super Pages) and insert the appropriate
PTE.&lt;/p&gt;

&lt;p&gt;Additionally, we modified the way we iterate through the BO’s memory. This was
necessary because the THP may not always allocate the entire BO contiguously.
For example, it might only allocate contiguously 1MB of a 2MB block. To handle
this, we now iterate over the blocks of contiguous memory scattered across the
scatterlist, ensuring that each segment is properly handled during the
allocation process.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;What is a scatterlist?&lt;/strong&gt; It is a Linux Kernel data structure that manages
non-contiguous memory as if it were contiguous. It organizes separate memory
blocks into a single logical buffer, allowing efficient data handling,
especially in Direct Memory Access (DMA) operations, without needing a
physically contiguous memory allocation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href=&quot;https://lore.kernel.org/dri-devel/20240923141348.2422499-9-mcanal@igalia.com/&quot;&gt;[PATCH v6 08/11] drm/v3d: Support Big/Super Pages when writing out PTEs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, the last few patches alone don’t fully enable the use of Super Pages.
While PATCH 08/11 technically allows for Super Pages, we’re still relying on DRM
GEM shmem objects, meaning allocations are still happening in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PAGE_SIZE&lt;/code&gt;
chunks. Although Big/Super Pages could potentially be used if the system
naturally allocated 1MB or 64KB contiguously, this is quite rare and not our
intended outcome. Our goal is to actively use Big/Super Pages as much as
possible.&lt;/p&gt;

&lt;p&gt;To achieve this, we’ll utilize the V3D-specific mountpoint we created earlier
for BO allocation whenever possible. By creating BOs through
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drm_gem_shmem_create_with_mnt()&lt;/code&gt;, we can ensure that large pages are allocated
contiguously when possible, enabling the consistent use of Big/Super Pages.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://lore.kernel.org/dri-devel/20240923141348.2422499-10-mcanal@igalia.com/&quot;&gt;[PATCH v6 09/11] drm/v3d: Use gemfs/THP in BO creation if available&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And there you have it — Big/Super Pages are now fully enabled in V3D. The only
requirement to activate this feature in any given kernel is ensuring that
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CONFIG_TRANSPARENT_HUGEPAGE&lt;/code&gt; is enabled.&lt;/p&gt;

&lt;h2 id=&quot;final-words&quot;&gt;Final Words&lt;/h2&gt;

&lt;p&gt;You can learn more about ongoing enhancements to the Raspberry Pi driver stack
in this &lt;a href=&quot;https://youtu.be/tlSFHkp6ODM?si=YVuLqbp9tYQkK6PD&quot;&gt;XDC 2024 talk&lt;/a&gt; by
José María “Chema” Casanova Crespo. In the talk, Chema discusses the Super
Pages work I developed, along with other advancements in the driver stack.&lt;/p&gt;

&lt;p&gt;Of course, there are still plenty of improvements on the horizon at Igalia. I’m
currently experimenting with 64KB CLE allocations in user-space, and I hope to
share more good news soon.&lt;/p&gt;

&lt;p&gt;Finally, I’d like to express my gratitude to &lt;a href=&quot;https://blogs.igalia.com/itoral/&quot;&gt;Iago
Toral&lt;/a&gt; and &lt;a href=&quot;https://blogs.igalia.com/tursulin/&quot;&gt;Tvrtko
Ursulin&lt;/a&gt; for their invaluable support in
developing Super Pages for the V3D kernel driver. Thank you both for sharing
your experience with me!&lt;/p&gt;

</description>
                <pubDate>Mon, 28 Oct 2024 12:00:00 +0000</pubDate>
                <link>https://mairacanal.github.io/unleashing-power-enabling-super-pages-on-RPi/</link>
                <guid isPermaLink="true">https://mairacanal.github.io/unleashing-power-enabling-super-pages-on-RPi/</guid>
            </item>
        
            <item>
                <title>Linux 6.8: AMD HDR and Raspberry Pi 5</title>
                
                <description>&lt;p&gt;The Linux kernel 6.8 came out on March 10th, 2024, bringing brand-new features
and plenty of performance improvements on different subsystems. As part of
&lt;a href=&quot;https://www.igalia.com/&quot;&gt;Igalia&lt;/a&gt;, I’m happy to be an active part of many
features that are released in this version, and today I’m going to review some
of them.&lt;/p&gt;

&lt;p&gt;Linux 6.8 is packed with a lot of great features, performance optimizations, and
new hardware support. In this release, we can check the Intel Xe DRM driver
experimentally, further support for AMD Zen 5 and other upcoming AMD hardware,
initial support for the Qualcomm Snapdragon 8 Gen 3 SoC, the Imagination PowerVR
DRM kernel driver, support for the Nintendo NSO controllers, and much more.&lt;/p&gt;

&lt;p&gt;Igalia is widely known for its contributions to Web Platforms, Chromium, and
Mesa. But, we also make significant contributions to the Linux kernel. This
release shows some of the great work that Igalia is putting into the kernel and
strengthens our desire to keep working with this great community.&lt;/p&gt;

&lt;p&gt;Let’s take a deep dive into Igalia’s major contributions to the 6.8 release:&lt;/p&gt;

&lt;h2 id=&quot;amd-hdr--color-management&quot;&gt;AMD HDR &amp;amp; Color Management&lt;/h2&gt;

&lt;p&gt;You may have seen the release of a new Steam Deck last year, the Steam Deck
OLED. What you may not know is that Igalia helped bring this product to life by
putting some effort into the AMD driver-specific color management properties
implementation. &lt;a href=&quot;https://www.igalia.com/team/mwen&quot;&gt;Melissa Wen&lt;/a&gt;, together with
Joshua Ashton (Valve), and Harry Wentland (AMD), implemented several
driver-specific properties to allow Gamescope to manage color features provided
by the AMD hardware to fit HDR content and improve gamers’ experience.&lt;/p&gt;

&lt;p&gt;She has explained all features implemented in the AMD display kernel driver in
two blog posts and a 2023 XDC talk:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://melissawen.github.io/blog/2023/08/21/amd-steamdeck-colors&quot;&gt;AMD Driver-specific Properties for Color Management on Linux (Part 1)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://melissawen.github.io/blog/2023/11/07/amd-steamdeck-colors-p2&quot;&gt;AMD Driver-specific Properties for Color Management on Linux (Part 2)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://melissawen.github.io/blog/2023/12/20/xdc2023-colors-talk&quot;&gt;The Rainbow Treasure Map Talk: Advanced color management on Linux with AMD/Steam Deck&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;async-flip&quot;&gt;Async Flip&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://www.igalia.com/team/tonyk&quot;&gt;André Almeida&lt;/a&gt; worked together with Simon
Ser (SourceHut) to provide support for asynchronous page-flips in the atomic
API. This feature targets users who want to present a new frame immediately,
even if after missing a V-blank. This feature is particularly useful for
applications with high frame rates, such as gaming.&lt;/p&gt;

&lt;h2 id=&quot;raspberry-pi-5&quot;&gt;Raspberry Pi 5&lt;/h2&gt;

&lt;p&gt;Raspberry Pi 5 was officially released on October 2023 and Igalia was ready to
bring top-notch graphics support for it. Although we still can’t use the RPi 5
with the mainline kernel, it is superb to see some pieces coming upstream. &lt;a href=&quot;https://www.igalia.com/team/itoral&quot;&gt;Iago
Toral&lt;/a&gt; worked on implementing all the kernel
support needed for the V3D 7.1.x driver.&lt;/p&gt;

&lt;p&gt;With the kernel patches, by the time the RPi 5 was released, it already included
a fully 3.1 OpenGL ES and Vulkan 1.2 compliant driver implemented by Igalia.&lt;/p&gt;

&lt;h2 id=&quot;gpu-stats-and-cpu-jobs-for-the-raspberry-pi-45&quot;&gt;GPU stats and CPU jobs for the Raspberry Pi 4/5&lt;/h2&gt;

&lt;p&gt;Apart from the release of the Raspberry Pi 5, Igalia is still working on
improving the whole Raspberry Pi environment. I worked, together with &lt;a href=&quot;https://www.igalia.com/team/chema&quot;&gt;José
Maria “Chema” Casanova&lt;/a&gt;, implementing the
support for GPU stats on the V3D driver. This means that RPi 4/5 users now can
access the usage percentage of the GPU and they can access the statistics by
process or globally.&lt;/p&gt;

&lt;p&gt;I also worked, together with &lt;a href=&quot;https://www.igalia.com/team/mwen&quot;&gt;Melissa&lt;/a&gt;,
implementing CPU jobs for the V3D driver. As the Broadcom GPU isn’t capable of
performing some operations, the Vulkan driver uses the CPU to compensate for it.
In order to avoid stalls in the job submission, now CPU jobs are part of the
kernel and can be easily synchronized though with synchronization objects.&lt;/p&gt;

&lt;p&gt;If you are curious about the CPU job implementation, you can check this &lt;a href=&quot;https://mairacanal.github.io/introducing-cpu-jobs-to-the-rpi/&quot;&gt;blog
post&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;other-contributions--fixes&quot;&gt;Other Contributions &amp;amp; Fixes&lt;/h2&gt;

&lt;p&gt;Sometimes we don’t contribute to a major feature in the release, however we can
help improving documentation and sending fixes.
&lt;a href=&quot;https://www.igalia.com/team/tonyk&quot;&gt;André&lt;/a&gt; also contributed to this release by
documenting the different AMD GPU reset methods, making it easier to understand
by future users.&lt;/p&gt;

&lt;p&gt;During Igalia’s efforts to improve the general users’ experience on the Steam
Deck, &lt;a href=&quot;https://www.igalia.com/team/gpiccoli&quot;&gt;Guilherme G. Piccoli&lt;/a&gt; noticed a
message in the kernel log and readily provided a fix for this PCI issue.&lt;/p&gt;

&lt;p&gt;Outside of the Steam Deck world, we can check some of Igalia’s work on the
Qualcomm Adreno GPUs. Although most of our Adreno-related work is located at the
user-space, &lt;a href=&quot;https://www.igalia.com/team/dpiliaiev&quot;&gt;Danylo Piliaiev&lt;/a&gt; sent a
couple of kernel fixes to the msm driver, fixing some hangs and some CTS tests.&lt;/p&gt;

&lt;p&gt;We also had contributions from our 2023 Igalia CE student, Nia Espera. Nia’s
project was related to mobile Linux and she managed to write a couple of patches
to the kernel in order to add support for the OnePlus 9 and OnePlus 9 Pro
devices.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;If you are a student interested in open-source and would like to have a first
exposure to the professional world, check if we have openings for the &lt;a href=&quot;https://www.igalia.com/coding-experience/&quot;&gt;Igalia
Coding Experience&lt;/a&gt;. I was a CE
student myself and being mentored by a Igalian was a incredible experience.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;check-the-complete-list-of-igalias-contributions-for-the-68-release&quot;&gt;Check the complete list of Igalia’s contributions for the 6.8 release&lt;/h2&gt;

&lt;h3 id=&quot;authored-57&quot;&gt;Authored (57):&lt;/h3&gt;

&lt;h4 id=&quot;andré-almeida-2&quot;&gt;André Almeida (2)&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=0e26cc72c71cb98e951716a6596060cd04b0ba6b&quot;&gt;drm: Refuse to async flip with atomic prop changes&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=613ecd6563d2716192e69624105fe1939d104663&quot;&gt;drm/amd: Document device reset methods&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;danylo-piliaiev-2&quot;&gt;Danylo Piliaiev (2)&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=cf1aaa7d4a719f0bdd9c246c0fac8247cb54ddd7&quot;&gt;drm/msm/a6xx: Add missing BIT(7) to REG_A6XX_UCHE_CLIENT_PF&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=07e6de738aa6f0e873463e9ca88bdb7081c4bfd4&quot;&gt;drm/msm/a690: Fix reg values for a690&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;guilherme-g-piccoli-1&quot;&gt;Guilherme G. Piccoli (1)&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=e585a37e5061f6d5060517aed1ca4ccb2e56a34c&quot;&gt;PCI: Only override AMD USB controller if required&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;iago-toral-quiroga-4&quot;&gt;Iago Toral Quiroga (4)&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=1118d10f5e5ab544c489fad4da373f9988416ece&quot;&gt;drm/v3d: update UAPI to match user-space for V3D 7.x&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=0ad5bc1ce4634ce9b5eaf017b01399ec5e49a03d&quot;&gt;drm/v3d: fix up register addresses for V3D 7.x&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=ebb2f6eea688b9ffa46527c3e7570b2c347497b8&quot;&gt;dt-bindings: gpu: v3d: Add BCM2712’s compatible&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=6fd9487147c4f18ad77eea00bd8c9189eec74a3e&quot;&gt;drm/v3d: add brcm,2712-v3d as a compatible V3D device&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;maíra-canal-17&quot;&gt;Maíra Canal (17)&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=79d94360d50fcd487edcfe118a47a2881534923f&quot;&gt;drm/v3d: wait for all jobs to finish before unregistering&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=09a93cc4f7d1893777f6b788bffe60d64e4d5df7&quot;&gt;drm/v3d: Implement show_fdinfo() callback for GPU usage stats&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=509433d8146c64ca9e0bcc370ec910821fffe80c&quot;&gt;drm/v3d: Expose the total GPU usage stats on sysfs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=c400eb4d6f5f603f4f3f6cc4b6fdacd416ff142e&quot;&gt;MAINTAINERS: Add Maira to V3D maintainers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=6893deb881ab7da1691bd05045ffcc0c806319b9&quot;&gt;drm/v3d: Don’t allow two multisync extensions in the same job&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=464c61e76de851a216e667c91332172c68ffed54&quot;&gt;drm/v3d: Decouple job allocation from job initiation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=c5195d001f4c122032a9ce90c6b88d772673fa35&quot;&gt;drm/v3d: Use v3d_get_extensions() to parse CPU job data&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=1fe0879efc8f623816c7a825d853d2140c88cb2d&quot;&gt;drm/v3d: Create tracepoints to track the CPU job&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=7c13132c4073628b5fe23b5188ac583a2882a6b0&quot;&gt;drm/v3d: Enable BO mapping&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=18b8413b25b7070fa2e55858a2c808e6909581d0&quot;&gt;drm/v3d: Create a CPU job extension for a indirect CSD job&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=9ba0ff3e083f6a4a0b6698f06bfff74805fefa5f&quot;&gt;drm/v3d: Create a CPU job extension for the timestamp query job&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=34a101e64296c736b14ce27e647fcebd70cb7bf8&quot;&gt;drm/v3d: Create a CPU job extension for the reset timestamp job&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=6745f3e44a20ac18e7e5a40a3c7f62225983d544&quot;&gt;drm/v3d: Create a CPU job extension to copy timestamp query to a buffer&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=bae7cb5d68001a8d4ceec5964dda74bb9aab7220&quot;&gt;drm/v3d: Create a CPU job extension for the reset performance query job&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=209e8d2695ee7a67a5b0487bbd1aa75e290d0f41&quot;&gt;drm/v3d: Create a CPU job extension for the copy performance query job&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=89fe46019a62bc1d0cb49c9615cb3520096c4bc1&quot;&gt;drm/v3d: Fix support for register debugging on the RPi 4&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=2ad62d16cd24b5e2f18318e97e1f06bef9f1ce7d&quot;&gt;drm/v3d: Free the job and assign it to NULL if initialization fails&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;melissa-wen-27&quot;&gt;Melissa Wen (27)&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=780b9463ce66a9efb18e3b5d35cd011fb918d741&quot;&gt;drm/v3d: Remove unused function header&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=a8ad9d63a160f6b93f6958a5a0ded1a6abb15815&quot;&gt;drm/v3d: Move wait BO ioctl to the v3d_bo file&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=9032d5f633ed7b5c726971dc7e2372045bf27f40&quot;&gt;drm/v3d: Detach job submissions IOCTLs to a new specific file&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=8288faaa8b3817c2fcdbacc720527bb8df2b57b1&quot;&gt;drm/v3d: Simplify job refcount handling&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=aafc1a2bea67460c41a289e8bb1e4dc6d016fe11&quot;&gt;drm/v3d: Add a CPU job submission&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=369b05961731925e4a43608ea1e7884df200f0bd&quot;&gt;drm/v3d: Detach the CSD job BO setup&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=1e13c5644c443dee727ac1330bc118c909a1cf07&quot;&gt;drm/drm_mode_object: increase max objects to accommodate new color props&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=601603105325ad4ec62db95c9bc428202ece2c8f&quot;&gt;drm/drm_property: make replace_property_blob_from_id a DRM helper&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=24013b9301349881c9fcd27e7edacc672e0bf6d3&quot;&gt;drm/drm_plane: track color mgmt changes per plane&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=9342a9ae54ef299ffe5e4ce3d0be6a4da5edba0e&quot;&gt;drm/amd/display: add driver-specific property for plane degamma LUT&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=5a3b965b5810bd602d2c7d8ea79ffe8c6e81268d&quot;&gt;drm/amd/display: explicitly define EOTF and inverse EOTF&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=e4cddd51bfab2a40529a4af35bd2c912b5a0c239&quot;&gt;drm/amd/display: document AMDGPU pre-defined transfer functions&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=671994e3bf33a414dc6a8c147969dae3a15ba9de&quot;&gt;drm/amd/display: add plane 3D LUT driver-specific properties&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=f545d82479b46368bf00d0bfecf33fa914bd5f8f&quot;&gt;drm/amd/display: add plane shaper LUT and TF driver-specific properties&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=0f5afa190b890052cae187496f660699f00067ef&quot;&gt;drm/amd/display: add CRTC gamma TF driver-specific property&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=98fbb52772063ad2547d6d1b80ff99bc26761e79&quot;&gt;drm/amd/display: add comments to describe DM crtc color mgmt behavior&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=8b6b3f668f31a24b5406661388b9a69202e83e9d&quot;&gt;drm/amd/display: encapsulate atomic regamma operation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=73e5ea616a9f8c261d07e63b421947949ad6cbce&quot;&gt;drm/amd/display: decouple steps for mapping CRTC degamma to DC plane&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=ef113a3b1964b40dd87287806865b947d70f7df5&quot;&gt;drm/amd/display: reject atomic commit if setting both plane and CRTC degamma&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=aba8b76baabde681ab4ff686452005d80d949345&quot;&gt;drm/amd/display: add plane shaper LUT support&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=99de686115b00e765a5e9345e10c9d7312e4c7ea&quot;&gt;drm/amd/display: add plane shaper TF support&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=486c95af5d76047d5cb50727270b1961dacb9380&quot;&gt;drm/amd/display: add plane 3D LUT support&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=c6ef0a2265c518aa6699b64d10a7e5a9049ac96a&quot;&gt;drm/amd/display: fix documentation for dm_crtc_additional_color_mgmt()&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=3a0fa3bc245ef92838a8296e0055569b8dff94c4&quot;&gt;drm/amd/display: fix bandwidth validation failure on DCN 2.1&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=7075893d1d68b2b3517be250a02d86e76554ed22&quot;&gt;drm/amd/display: cleanup inconsistent indenting in amdgpu_dm_color&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=9671761792156f2339627918bafcd713a8a6f777&quot;&gt;drm/amd/display: fix null-pointer dereference on edid reading&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=e9098cc9aef13bd56e821f628c83f709d3347af1&quot;&gt;drm/amd/display: check dc_link before dereferencing&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;nia-espera-4&quot;&gt;Nia Espera (4)&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=7bf421f44549cd0bca32bd0b4cf6e4cfe5b4f865&quot;&gt;dt-bindings: iio: adc: qcom: Add Qualcomm smb139x&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=01a9e9eb6cdbce175ddea3cbe1163daed6d54344&quot;&gt;arm64: dts: qcom: sm8350: Fix DMA0 address&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=e70537717146b380e18f0c92669d968af4acb8a7&quot;&gt;arm64: dts: qcom: pm8350k: Remove hanging whitespace&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=54ee322f845c7f25fbf6e43e11147b6cae8eff56&quot;&gt;arm64: dts: qcom: sm8350: Fix remoteproc interrupt type&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;signed-off-by-88&quot;&gt;Signed-off-by (88):&lt;/h3&gt;

&lt;h4 id=&quot;andré-almeida-4&quot;&gt;André Almeida (4)&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=0e26cc72c71cb98e951716a6596060cd04b0ba6b&quot;&gt;drm: Refuse to async flip with atomic prop changes&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=4b4af74ab9719d17538a97f43137e93296ec7437&quot;&gt;drm: allow DRM_MODE_PAGE_FLIP_ASYNC for atomic commits&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=e4d983acffff270ccee417445a69b9ed198658b1&quot;&gt;drm: introduce DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=613ecd6563d2716192e69624105fe1939d104663&quot;&gt;drm/amd: Document device reset methods&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;danylo-piliaiev-2-1&quot;&gt;Danylo Piliaiev (2)&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=cf1aaa7d4a719f0bdd9c246c0fac8247cb54ddd7&quot;&gt;drm/msm/a6xx: Add missing BIT(7) to REG_A6XX_UCHE_CLIENT_PF&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=07e6de738aa6f0e873463e9ca88bdb7081c4bfd4&quot;&gt;drm/msm/a690: Fix reg values for a690&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;guilherme-g-piccoli-1-1&quot;&gt;Guilherme G. Piccoli (1)&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=e585a37e5061f6d5060517aed1ca4ccb2e56a34c&quot;&gt;PCI: Only override AMD USB controller if required&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;iago-toral-quiroga-4-1&quot;&gt;Iago Toral Quiroga (4)&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=1118d10f5e5ab544c489fad4da373f9988416ece&quot;&gt;drm/v3d: update UAPI to match user-space for V3D 7.x&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=0ad5bc1ce4634ce9b5eaf017b01399ec5e49a03d&quot;&gt;drm/v3d: fix up register addresses for V3D 7.x&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=ebb2f6eea688b9ffa46527c3e7570b2c347497b8&quot;&gt;dt-bindings: gpu: v3d: Add BCM2712’s compatible&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=6fd9487147c4f18ad77eea00bd8c9189eec74a3e&quot;&gt;drm/v3d: add brcm,2712-v3d as a compatible V3D device&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;jose-maria-casanova-crespo-2&quot;&gt;Jose Maria Casanova Crespo (2)&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=09a93cc4f7d1893777f6b788bffe60d64e4d5df7&quot;&gt;drm/v3d: Implement show_fdinfo() callback for GPU usage stats&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=509433d8146c64ca9e0bcc370ec910821fffe80c&quot;&gt;drm/v3d: Expose the total GPU usage stats on sysfs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;maíra-canal-28&quot;&gt;Maíra Canal (28)&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=79d94360d50fcd487edcfe118a47a2881534923f&quot;&gt;drm/v3d: wait for all jobs to finish before unregistering&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=1118d10f5e5ab544c489fad4da373f9988416ece&quot;&gt;drm/v3d: update UAPI to match user-space for V3D 7.x&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=0ad5bc1ce4634ce9b5eaf017b01399ec5e49a03d&quot;&gt;drm/v3d: fix up register addresses for V3D 7.x&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=ebb2f6eea688b9ffa46527c3e7570b2c347497b8&quot;&gt;dt-bindings: gpu: v3d: Add BCM2712’s compatible&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=6fd9487147c4f18ad77eea00bd8c9189eec74a3e&quot;&gt;drm/v3d: add brcm,2712-v3d as a compatible V3D device&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=09a93cc4f7d1893777f6b788bffe60d64e4d5df7&quot;&gt;drm/v3d: Implement show_fdinfo() callback for GPU usage stats&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=509433d8146c64ca9e0bcc370ec910821fffe80c&quot;&gt;drm/v3d: Expose the total GPU usage stats on sysfs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=89d04995f76ce8318fe752feb33b1a45893b1a38&quot;&gt;MAINTAINERS: Drop Emma Anholt from all M lines.&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=c400eb4d6f5f603f4f3f6cc4b6fdacd416ff142e&quot;&gt;MAINTAINERS: Add Maira to V3D maintainers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=780b9463ce66a9efb18e3b5d35cd011fb918d741&quot;&gt;drm/v3d: Remove unused function header&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=a8ad9d63a160f6b93f6958a5a0ded1a6abb15815&quot;&gt;drm/v3d: Move wait BO ioctl to the v3d_bo file&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=9032d5f633ed7b5c726971dc7e2372045bf27f40&quot;&gt;drm/v3d: Detach job submissions IOCTLs to a new specific file&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=8288faaa8b3817c2fcdbacc720527bb8df2b57b1&quot;&gt;drm/v3d: Simplify job refcount handling&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=6893deb881ab7da1691bd05045ffcc0c806319b9&quot;&gt;drm/v3d: Don’t allow two multisync extensions in the same job&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=464c61e76de851a216e667c91332172c68ffed54&quot;&gt;drm/v3d: Decouple job allocation from job initiation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=aafc1a2bea67460c41a289e8bb1e4dc6d016fe11&quot;&gt;drm/v3d: Add a CPU job submission&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=c5195d001f4c122032a9ce90c6b88d772673fa35&quot;&gt;drm/v3d: Use v3d_get_extensions() to parse CPU job data&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=1fe0879efc8f623816c7a825d853d2140c88cb2d&quot;&gt;drm/v3d: Create tracepoints to track the CPU job&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=369b05961731925e4a43608ea1e7884df200f0bd&quot;&gt;drm/v3d: Detach the CSD job BO setup&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=7c13132c4073628b5fe23b5188ac583a2882a6b0&quot;&gt;drm/v3d: Enable BO mapping&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=18b8413b25b7070fa2e55858a2c808e6909581d0&quot;&gt;drm/v3d: Create a CPU job extension for a indirect CSD job&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=9ba0ff3e083f6a4a0b6698f06bfff74805fefa5f&quot;&gt;drm/v3d: Create a CPU job extension for the timestamp query job&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=34a101e64296c736b14ce27e647fcebd70cb7bf8&quot;&gt;drm/v3d: Create a CPU job extension for the reset timestamp job&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=6745f3e44a20ac18e7e5a40a3c7f62225983d544&quot;&gt;drm/v3d: Create a CPU job extension to copy timestamp query to a buffer&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=bae7cb5d68001a8d4ceec5964dda74bb9aab7220&quot;&gt;drm/v3d: Create a CPU job extension for the reset performance query job&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=209e8d2695ee7a67a5b0487bbd1aa75e290d0f41&quot;&gt;drm/v3d: Create a CPU job extension for the copy performance query job&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=89fe46019a62bc1d0cb49c9615cb3520096c4bc1&quot;&gt;drm/v3d: Fix support for register debugging on the RPi 4&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=2ad62d16cd24b5e2f18318e97e1f06bef9f1ce7d&quot;&gt;drm/v3d: Free the job and assign it to NULL if initialization fails&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;melissa-wen-43&quot;&gt;Melissa Wen (43)&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=780b9463ce66a9efb18e3b5d35cd011fb918d741&quot;&gt;drm/v3d: Remove unused function header&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=a8ad9d63a160f6b93f6958a5a0ded1a6abb15815&quot;&gt;drm/v3d: Move wait BO ioctl to the v3d_bo file&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=9032d5f633ed7b5c726971dc7e2372045bf27f40&quot;&gt;drm/v3d: Detach job submissions IOCTLs to a new specific file&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=8288faaa8b3817c2fcdbacc720527bb8df2b57b1&quot;&gt;drm/v3d: Simplify job refcount handling&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=aafc1a2bea67460c41a289e8bb1e4dc6d016fe11&quot;&gt;drm/v3d: Add a CPU job submission&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=369b05961731925e4a43608ea1e7884df200f0bd&quot;&gt;drm/v3d: Detach the CSD job BO setup&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=18b8413b25b7070fa2e55858a2c808e6909581d0&quot;&gt;drm/v3d: Create a CPU job extension for a indirect CSD job&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=1e13c5644c443dee727ac1330bc118c909a1cf07&quot;&gt;drm/drm_mode_object: increase max objects to accommodate new color props&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=601603105325ad4ec62db95c9bc428202ece2c8f&quot;&gt;drm/drm_property: make replace_property_blob_from_id a DRM helper&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=24013b9301349881c9fcd27e7edacc672e0bf6d3&quot;&gt;drm/drm_plane: track color mgmt changes per plane&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=9342a9ae54ef299ffe5e4ce3d0be6a4da5edba0e&quot;&gt;drm/amd/display: add driver-specific property for plane degamma LUT&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=d5a348d96e4e2b924fa83e729f8791c03a4f8e24&quot;&gt;drm/amd/display: add plane degamma TF driver-specific property&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=5a3b965b5810bd602d2c7d8ea79ffe8c6e81268d&quot;&gt;drm/amd/display: explicitly define EOTF and inverse EOTF&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=e4cddd51bfab2a40529a4af35bd2c912b5a0c239&quot;&gt;drm/amd/display: document AMDGPU pre-defined transfer functions&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=ec7b2a55463ea50401a8146793b61ee590255a45&quot;&gt;drm/amd/display: add plane HDR multiplier driver-specific property&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=671994e3bf33a414dc6a8c147969dae3a15ba9de&quot;&gt;drm/amd/display: add plane 3D LUT driver-specific properties&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=f545d82479b46368bf00d0bfecf33fa914bd5f8f&quot;&gt;drm/amd/display: add plane shaper LUT and TF driver-specific properties&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=0ef47454dc82358b62a424b37c7520a84f307edb&quot;&gt;drm/amd/display: add plane blend LUT and TF driver-specific properties&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=0f5afa190b890052cae187496f660699f00067ef&quot;&gt;drm/amd/display: add CRTC gamma TF driver-specific property&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=98fbb52772063ad2547d6d1b80ff99bc26761e79&quot;&gt;drm/amd/display: add comments to describe DM crtc color mgmt behavior&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=8b6b3f668f31a24b5406661388b9a69202e83e9d&quot;&gt;drm/amd/display: encapsulate atomic regamma operation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=6bd20f0f165f444c1d8184ebd238dd92966c9dca&quot;&gt;drm/amd/display: add CRTC gamma TF support&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=88d26ea639a8e9d314e6bffef5f382167e7203e2&quot;&gt;drm/amd/display: set sdr_ref_white_level to 80 for out_transfer_func&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=6bed9d550e51534415a56f8de33f5b9d4e728e53&quot;&gt;drm/amd/display: mark plane as needing reset if color props change&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=73e5ea616a9f8c261d07e63b421947949ad6cbce&quot;&gt;drm/amd/display: decouple steps for mapping CRTC degamma to DC plane&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=980f8710075acaeb226a94cde6dda8ffad30123c&quot;&gt;drm/amd/display: add plane degamma TF and LUT support&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=ef113a3b1964b40dd87287806865b947d70f7df5&quot;&gt;drm/amd/display: reject atomic commit if setting both plane and CRTC degamma&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=889044f9e04f0829dd92640c551941bbe77bc0ea&quot;&gt;drm/amd/display: add dc_fixpt_from_s3132 helper&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=4bc59ddf57c1f68ea035c4f242108f29d91797fd&quot;&gt;drm/amd/display: add HDR multiplier support&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=aba8b76baabde681ab4ff686452005d80d949345&quot;&gt;drm/amd/display: add plane shaper LUT support&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=99de686115b00e765a5e9345e10c9d7312e4c7ea&quot;&gt;drm/amd/display: add plane shaper TF support&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=486c95af5d76047d5cb50727270b1961dacb9380&quot;&gt;drm/amd/display: add plane 3D LUT support&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=8d26795ae61a5f64ba7db4f3240dc9ab2138d361&quot;&gt;drm/amd/display: handle empty LUTs in __set_input_tf&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=783ed4460fe55b01ff32a7c6ad8239974874a16a&quot;&gt;drm/amd/display: add plane blend LUT and TF support&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=f81996637000a050477d597ef99e832079f99bd2&quot;&gt;drm/amd/display: allow newer DC hardware to use degamma ROM for PQ/HLG&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=cb19dc4a64598ffbfd4354083f809fae082fa4c3&quot;&gt;drm/amd/display: copy 3D LUT settings from crtc state to stream_update&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=b8b92c1bd7788b1f13d547ee2ce8a93baf55b814&quot;&gt;drm/amd/display: add plane CTM driver-specific property&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=3dad69090743c5f4642aeb628b8542a1e335dded&quot;&gt;drm/amd/display: add plane CTM support&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=c6ef0a2265c518aa6699b64d10a7e5a9049ac96a&quot;&gt;drm/amd/display: fix documentation for dm_crtc_additional_color_mgmt()&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=3a0fa3bc245ef92838a8296e0055569b8dff94c4&quot;&gt;drm/amd/display: fix bandwidth validation failure on DCN 2.1&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=7075893d1d68b2b3517be250a02d86e76554ed22&quot;&gt;drm/amd/display: cleanup inconsistent indenting in amdgpu_dm_color&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=9671761792156f2339627918bafcd713a8a6f777&quot;&gt;drm/amd/display: fix null-pointer dereference on edid reading&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=e9098cc9aef13bd56e821f628c83f709d3347af1&quot;&gt;drm/amd/display: check dc_link before dereferencing&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;nia-espera-4-1&quot;&gt;Nia Espera (4)&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=7bf421f44549cd0bca32bd0b4cf6e4cfe5b4f865&quot;&gt;dt-bindings: iio: adc: qcom: Add Qualcomm smb139x&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=01a9e9eb6cdbce175ddea3cbe1163daed6d54344&quot;&gt;arm64: dts: qcom: sm8350: Fix DMA0 address&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=e70537717146b380e18f0c92669d968af4acb8a7&quot;&gt;arm64: dts: qcom: pm8350k: Remove hanging whitespace&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=54ee322f845c7f25fbf6e43e11147b6cae8eff56&quot;&gt;arm64: dts: qcom: sm8350: Fix remoteproc interrupt type&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;acked-by-4&quot;&gt;Acked-by (4):&lt;/h3&gt;

&lt;h4 id=&quot;jose-maria-casanova-crespo-2-1&quot;&gt;Jose Maria Casanova Crespo (2)&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=09a93cc4f7d1893777f6b788bffe60d64e4d5df7&quot;&gt;drm/v3d: Implement show_fdinfo() callback for GPU usage stats&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=509433d8146c64ca9e0bcc370ec910821fffe80c&quot;&gt;drm/v3d: Expose the total GPU usage stats on sysfs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;maíra-canal-1&quot;&gt;Maíra Canal (1)&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=89d04995f76ce8318fe752feb33b1a45893b1a38&quot;&gt;MAINTAINERS: Drop Emma Anholt from all M lines.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;melissa-wen-1&quot;&gt;Melissa Wen (1)&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=c400eb4d6f5f603f4f3f6cc4b6fdacd416ff142e&quot;&gt;MAINTAINERS: Add Maira to V3D maintainers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;reviewed-by-30&quot;&gt;Reviewed-by (30):&lt;/h3&gt;

&lt;h4 id=&quot;andré-almeida-1&quot;&gt;André Almeida (1)&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=e4d983acffff270ccee417445a69b9ed198658b1&quot;&gt;drm: introduce DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;christian-gmeiner-1&quot;&gt;Christian Gmeiner (1)&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=d437dab5b06e3dc73f6a58a6c9fd0b13d1ed80e1&quot;&gt;drm/etnaviv: Convert to platform remove callback returning void&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;iago-toral-quiroga-20&quot;&gt;Iago Toral Quiroga (20)&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=79d94360d50fcd487edcfe118a47a2881534923f&quot;&gt;drm/v3d: wait for all jobs to finish before unregistering&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=780b9463ce66a9efb18e3b5d35cd011fb918d741&quot;&gt;drm/v3d: Remove unused function header&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=a8ad9d63a160f6b93f6958a5a0ded1a6abb15815&quot;&gt;drm/v3d: Move wait BO ioctl to the v3d_bo file&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=9032d5f633ed7b5c726971dc7e2372045bf27f40&quot;&gt;drm/v3d: Detach job submissions IOCTLs to a new specific file&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=8288faaa8b3817c2fcdbacc720527bb8df2b57b1&quot;&gt;drm/v3d: Simplify job refcount handling&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=6893deb881ab7da1691bd05045ffcc0c806319b9&quot;&gt;drm/v3d: Don’t allow two multisync extensions in the same job&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=464c61e76de851a216e667c91332172c68ffed54&quot;&gt;drm/v3d: Decouple job allocation from job initiation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=aafc1a2bea67460c41a289e8bb1e4dc6d016fe11&quot;&gt;drm/v3d: Add a CPU job submission&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=c5195d001f4c122032a9ce90c6b88d772673fa35&quot;&gt;drm/v3d: Use v3d_get_extensions() to parse CPU job data&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=1fe0879efc8f623816c7a825d853d2140c88cb2d&quot;&gt;drm/v3d: Create tracepoints to track the CPU job&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=369b05961731925e4a43608ea1e7884df200f0bd&quot;&gt;drm/v3d: Detach the CSD job BO setup&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=7c13132c4073628b5fe23b5188ac583a2882a6b0&quot;&gt;drm/v3d: Enable BO mapping&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=18b8413b25b7070fa2e55858a2c808e6909581d0&quot;&gt;drm/v3d: Create a CPU job extension for a indirect CSD job&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=9ba0ff3e083f6a4a0b6698f06bfff74805fefa5f&quot;&gt;drm/v3d: Create a CPU job extension for the timestamp query job&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=34a101e64296c736b14ce27e647fcebd70cb7bf8&quot;&gt;drm/v3d: Create a CPU job extension for the reset timestamp job&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=6745f3e44a20ac18e7e5a40a3c7f62225983d544&quot;&gt;drm/v3d: Create a CPU job extension to copy timestamp query to a buffer&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=bae7cb5d68001a8d4ceec5964dda74bb9aab7220&quot;&gt;drm/v3d: Create a CPU job extension for the reset performance query job&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=209e8d2695ee7a67a5b0487bbd1aa75e290d0f41&quot;&gt;drm/v3d: Create a CPU job extension for the copy performance query job&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=89fe46019a62bc1d0cb49c9615cb3520096c4bc1&quot;&gt;drm/v3d: Fix support for register debugging on the RPi 4&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=2ad62d16cd24b5e2f18318e97e1f06bef9f1ce7d&quot;&gt;drm/v3d: Free the job and assign it to NULL if initialization fails&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;maíra-canal-4&quot;&gt;Maíra Canal (4)&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=1118d10f5e5ab544c489fad4da373f9988416ece&quot;&gt;drm/v3d: update UAPI to match user-space for V3D 7.x&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=0ad5bc1ce4634ce9b5eaf017b01399ec5e49a03d&quot;&gt;drm/v3d: fix up register addresses for V3D 7.x&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=ebb2f6eea688b9ffa46527c3e7570b2c347497b8&quot;&gt;dt-bindings: gpu: v3d: Add BCM2712’s compatible&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=6fd9487147c4f18ad77eea00bd8c9189eec74a3e&quot;&gt;drm/v3d: add brcm,2712-v3d as a compatible V3D device&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;melissa-wen-4&quot;&gt;Melissa Wen (4)&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=09a93cc4f7d1893777f6b788bffe60d64e4d5df7&quot;&gt;drm/v3d: Implement show_fdinfo() callback for GPU usage stats&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=509433d8146c64ca9e0bcc370ec910821fffe80c&quot;&gt;drm/v3d: Expose the total GPU usage stats on sysfs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=dce94061f0d02f5ab355390a6e63d3dbea938b72&quot;&gt;drm/v3d: Fix missing error code in v3d_submit_cpu_ioctl()&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=8b881b5d6fe9ebb7736097f37103c9b07ea45642&quot;&gt;drm/amd/display: fix documentation for amdgpu_dm_verify_lut3d_size()&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;tested-by-1&quot;&gt;Tested-by (1):&lt;/h3&gt;

&lt;h4 id=&quot;guilherme-g-piccoli-1-2&quot;&gt;Guilherme G. Piccoli (1)&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.8&amp;amp;id=d49270a04623ce3c0afddbf3e984cb245aa48e9c&quot;&gt;pstore/ram: Fix crash when setting number of cpus to an odd number&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
                <pubDate>Tue, 02 Apr 2024 11:00:00 +0000</pubDate>
                <link>https://mairacanal.github.io/linux-6-8-AMD-HDR-and-raspberry-pi-5/</link>
                <guid isPermaLink="true">https://mairacanal.github.io/linux-6-8-AMD-HDR-and-raspberry-pi-5/</guid>
            </item>
        
            <item>
                <title>Introducing CPU jobs to the Raspberry Pi</title>
                
                <description>&lt;p&gt;&lt;a href=&quot;https://www.igalia.com&quot;&gt;Igalia&lt;/a&gt; is always working hard to improve 3D rendering
drivers of the Broadcom VideoCore GPU, found in Raspberry Pi devices. One of our
most recent efforts in this sense was the implementation of CPU jobs from the
Vulkan driver to the V3D kernel driver.&lt;/p&gt;

&lt;h2 id=&quot;what-are-cpu-jobs-and-why-do-we-need-them&quot;&gt;What are CPU jobs and why do we need them?&lt;/h2&gt;

&lt;p&gt;In the V3DV driver, there are some Vulkan commands that cannot be performed by
the GPU alone, so we implement those as CPU jobs on Mesa. A CPU job is a job
that requires CPU intervention to be performed. For example, in the Broadcom
VideoCore GPUs, we don’t have a way to calculate the timestamp. But we need the
timestamp for Vulkan &lt;a href=&quot;https://docs.vulkan.org/samples/latest/samples/api/timestamp_queries/README.html&quot;&gt;timestamp
queries&lt;/a&gt;.
Therefore, we need to calculate the timestamp on the CPU.&lt;/p&gt;

&lt;p&gt;A CPU job in userspace also implies CPU stalling. Sometimes, we need to hold
part of the command submission flow in order to correctly synchronize their
execution. This waiting period caused the CPU to stall, thereby preventing the
continuous submission of jobs to the GPU. To mitigate this issue, we decided to
move CPU job mechanisms from the V3DV driver to the V3D kernel driver.&lt;/p&gt;

&lt;p&gt;In the V3D kernel driver, we have different kinds of jobs: RENDER jobs, BIN
jobs, CSD jobs, TFU jobs, and CLEAN CACHE jobs. For each of those jobs, we have
a DRM scheduler instance that helps us to synchronize the jobs.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;If you want to know more about the different kinds of V3D jobs, check out this
&lt;a href=&quot;https://mairacanal.github.io/november-update-exploring-v3d/&quot;&gt;November Update: Exploring
V3D&lt;/a&gt; blogpost,
where I explain more about all the V3D
&lt;a href=&quot;https://en.wikipedia.org/wiki/Ioctl&quot;&gt;IOCTLs&lt;/a&gt; and jobs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Jobs of the same kind are submitted, dispatched, and processed in the same order
they are executed, using a standard first-in-first-out (FIFO) queue system. We
can synchronize different jobs across different queues using DRM syncobjs. More
about the V3D synchronization framework and user extensions can be learned in
&lt;a href=&quot;https://melissawen.github.io/blog/2022/05/10/multisync-p1&quot;&gt;this two-part blog
post&lt;/a&gt; from Melissa
Wen.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;From the kernel documentation, a DRM syncobj (synchronisation objects) are
containers for stuff that helps sync up GPU commands. They’re super handy
because you can use them in your own programs, share them with other programs,
and even use them across different DRM drivers. Mostly, they’re used for
making Vulkan fences and semaphores work.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;By moving the CPU job from userspace to the kernel, we can make use of the DRM
schedule queues and all the advantages it brings with it. For this, we created a
new type of job in the V3D kernel driver, a CPU job, which also means creating a
new DRM scheduler instance and a CPU job queue. Now, instead of stalling the
submission thread waiting for the GPU to idle, we can use DRM syncobjs to
synchronize both CPU and GPU jobs in a submission, providing more efficient
usage of the GPU.&lt;/p&gt;

&lt;h2 id=&quot;how-did-we-implement-the-cpu-jobs-in-the-kernel-driver&quot;&gt;How did we implement the CPU jobs in the kernel driver?&lt;/h2&gt;

&lt;p&gt;After we decided to have a CPU job implementation in the kernel space, we could
think about two possible implementations for this job: creating an IOCTL for
each type of CPU job or using a user extension to provide a polymorphic behavior
to a single CPU job IOCTL.&lt;/p&gt;

&lt;p&gt;We have different types of CPU jobs (indirect CSD jobs, timestamp query jobs,
copy query results jobs…) and each of them has a common infrastructure
of allocation and synchronization but performs different operations. Therefore,
we decided to go with the option to use user extensions.&lt;/p&gt;

&lt;p&gt;On &lt;a href=&quot;https://melissawen.github.io/blog/2022/05/10/multisync-p1&quot;&gt;Melissa’s blogpost&lt;/a&gt;, she digs
deep into the implementation of generic IOCTL extensions in the V3D kernel
driver. But, to put it simply, instead of expanding the data struct for each
IOCTL every time we need to add a new feature, we define a user extension chain
instead. As we add new optional interfaces to control the IOCTL, we define a new
extension struct that can be linked to the IOCTL data only when required by the
user.&lt;/p&gt;

&lt;p&gt;Therefore, we created a new IOCTL, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drm_v3d_submit_cpu&lt;/code&gt;, which is used to submit
any type of CPU job. This single IOCTL can be extended by a user extension,
which allows us to reuse the common infrastructure - avoiding code
repetition - and yet use the user extension ID to identify the type of job
and depending on the type of job, perform a certain operation.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;drm_v3d_submit_cpu&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;cm&quot;&gt;/* Pointer to a u32 array of the BOs that are referenced by the job.
         *
         * For DRM_V3D_EXT_ID_CPU_INDIRECT_CSD, it must contain only one BO,
         * that contains the workgroup counts.
         *
         * For DRM_V3D_EXT_ID_TIMESTAMP_QUERY, it must contain only one BO,
         * that will contain the timestamp.
         *
         * For DRM_V3D_EXT_ID_CPU_RESET_TIMESTAMP_QUERY, it must contain only
         * one BO, that contains the timestamp.
         *
         * For DRM_V3D_EXT_ID_CPU_COPY_TIMESTAMP_QUERY, it must contain two
         * BOs. The first is the BO where the timestamp queries will be written
         * to. The second is the BO that contains the timestamp.
         *
         * For DRM_V3D_EXT_ID_CPU_RESET_PERFORMANCE_QUERY, it must contain no
         * BOs.
         *
         * For DRM_V3D_EXT_ID_CPU_COPY_PERFORMANCE_QUERY, it must contain one
         * BO, where the performance queries will be written.
         */&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;__u64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bo_handles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;cm&quot;&gt;/* Number of BO handles passed in (size is that times 4). */&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;__u32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bo_handle_count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;__u32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;cm&quot;&gt;/* Pointer to an array of ioctl extensions*/&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;__u64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;extensions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, we can create a CPU job and submit it with a CPU job user extension.&lt;/p&gt;

&lt;p&gt;And which extensions are available?&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://cgit.freedesktop.org/drm/drm-misc/commit/?id=18b8413b25b7070fa2e55858a2c808e6909581d0&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DRM_V3D_EXT_ID_CPU_INDIRECT_CSD&lt;/code&gt;&lt;/a&gt;:
this CPU job allows us to submit an indirect CSD job. An indirect CSD job is a
job that, when executed in the queue, will map an indirect buffer, read the
dispatch parameters, and submit a regular dispatch. This CPU job is used in
Vulkan calls like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vkCmdDispatchIndirect()&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://cgit.freedesktop.org/drm/drm-misc/commit/?id=9ba0ff3e083f6a4a0b6698f06bfff74805fefa5f&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DRM_V3D_EXT_ID_CPU_TIMESTAMP_QUERY&lt;/code&gt;&lt;/a&gt;:
this CPU job calculates the query timestamp and updates the query availability
by signaling a syncobj. This CPU job is used in Vulkan calls like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vkCmdWriteTimestamp()&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://cgit.freedesktop.org/drm/drm-misc/commit/?id=34a101e64296c736b14ce27e647fcebd70cb7bf8&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DRM_V3D_EXT_ID_CPU_RESET_TIMESTAMP_QUERY&lt;/code&gt;&lt;/a&gt;:
this CPU job resets the timestamp queries based on the value offset of the first
query. This CPU job is used in Vulkan calls like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vkCmdResetQueryPool()&lt;/code&gt; for timestamp queries.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://cgit.freedesktop.org/drm/drm-misc/commit/?id=6745f3e44a20ac18e7e5a40a3c7f62225983d544&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DRM_V3D_EXT_ID_CPU_COPY_TIMESTAMP_QUERY&lt;/code&gt;&lt;/a&gt;:
this CPU job copies the complete or partial result of a query to a buffer.
This CPU job is used in Vulkan calls like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vkCmdCopyQueryPoolResults()&lt;/code&gt; for timestamp queries.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://cgit.freedesktop.org/drm/drm-misc/commit/?id=bae7cb5d68001a8d4ceec5964dda74bb9aab7220&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DRM_V3D_EXT_ID_CPU_RESET_PERFORMANCE_QUERY&lt;/code&gt;&lt;/a&gt;:
this CPU job resets the performance queries by resetting the values of the
perfmons. This CPU job is used in Vulkan calls like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vkCmdResetQueryPool()&lt;/code&gt; for performance queries.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://cgit.freedesktop.org/drm/drm-misc/commit/?id=209e8d2695ee7a67a5b0487bbd1aa75e290d0f41&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DRM_V3D_EXT_ID_CPU_COPY_PERFORMANCE_QUERY&lt;/code&gt;&lt;/a&gt;:
similar to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DRM_V3D_EXT_ID_CPU_COPY_TIMESTAMP_QUERY&lt;/code&gt;, this CPU job copies the
complete or partial result of a query to a buffer. This CPU job is used in Vulkan
calls like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vkCmdCopyQueryPoolResults()&lt;/code&gt; for performance queries.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The CPU job IOCTL structure is similar to any other V3D job. We allocate the job
struct, parse all the extensions, init the job, look up the BOs and lock its
reservations, add the proper dependencies, and push the job to the DRM scheduler
entity.&lt;/p&gt;

&lt;p&gt;When running a CPU job, we execute the following code:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v3d_cpu_job_fn&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cpu_job_function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;V3D_CPU_JOB_TYPE_INDIRECT_CSD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v3d_rewrite_csd_job_wg_counts_from_indirect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;V3D_CPU_JOB_TYPE_TIMESTAMP_QUERY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v3d_timestamp_query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;V3D_CPU_JOB_TYPE_RESET_TIMESTAMP_QUERY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v3d_reset_timestamp_queries&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;V3D_CPU_JOB_TYPE_COPY_TIMESTAMP_QUERY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v3d_copy_query_results&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;V3D_CPU_JOB_TYPE_RESET_PERFORMANCE_QUERY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v3d_reset_performance_queries&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;V3D_CPU_JOB_TYPE_COPY_PERFORMANCE_QUERY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v3d_copy_performance_query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dma_fence&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;v3d_cpu_job_run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;drm_sched_job&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sched_job&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v3d_cpu_job&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;job&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to_cpu_job&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sched_job&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v3d_dev&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v3d&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;job&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v3d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;v3d&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cpu_job&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;job&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;job&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;job_type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ARRAY_SIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cpu_job_function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;DRM_DEBUG_DRIVER&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Unknown CPU job: %d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;job&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;job_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;trace_v3d_cpu_job_begin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v3d&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;drm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;job&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;job_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;cpu_job_function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;job&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;job_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;job&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;trace_v3d_cpu_job_end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v3d&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;drm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;job&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;job_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The interesting thing is that each CPU job type executes a completely different operation.&lt;/p&gt;

&lt;p&gt;The complete kernel implementation has already landed in drm-misc-next and can
be seen right
&lt;a href=&quot;https://lore.kernel.org/dri-devel/20231130164420.932823-2-mcanal@igalia.com/T/&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;what-did-we-change-in-mesa-v3dv-to-use-the-new-kernel-v3d-cpu-job&quot;&gt;What did we change in Mesa-V3DV to use the new kernel-V3D CPU job?&lt;/h2&gt;

&lt;p&gt;After landing the kernel implementation, I needed to accommodate the new CPU job
approach in the userspace.&lt;/p&gt;

&lt;p&gt;A fundamental rule is not to cause regressions, i.e., to keep backwards
userspace compatibility with old versions of the Linux kernel. This means we
cannot break new versions of Mesa running in old kernels. Therefore, we needed
to create two paths: one preserving the old way to perform CPU jobs and the
other using the kernel to perform CPU jobs.&lt;/p&gt;

&lt;p&gt;So, for example, the indirect CSD job used to add two different jobs to the
queue: a CPU job and a CSD job. Now, if we have the CPU job capability in the
kernel, we only add a CPU job and the CSD job is dispatched from within the
kernel.&lt;/p&gt;

&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gd&quot;&gt;-   list_addtail(&amp;amp;csd_job-&amp;gt;list_link, &amp;amp;cmd_buffer-&amp;gt;jobs);
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+
+   /* If we have a CPU queue we submit the CPU job directly to the
+    * queue and the CSD job will be dispatched from within the kernel
+    * queue, otherwise we will have to dispatch the CSD job manually
+    * right after the CPU job by adding it to the list of jobs in the
+    * command buffer.
+    */
+   if (!cmd_buffer-&amp;gt;device-&amp;gt;pdevice-&amp;gt;caps.cpu_queue)
+      list_addtail(&amp;amp;csd_job-&amp;gt;list_link, &amp;amp;cmd_buffer-&amp;gt;jobs);
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Furthermore, now we can use syncobjs to sync the CPU jobs. For example, in the
timestamp query CPU job, we used to stall the submission thread and wait for
completion of all work queued before the timestamp query. Now, we can just add a
barrier to the CPU job and it will be properly synchronized by the syncobjs
without stalling the submission thread.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;   &lt;span class=&quot;cm&quot;&gt;/* The CPU job should be serialized so it only executes after all previously
    * submitted work has completed
    */&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;job&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;serialize&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;V3DV_BARRIER_ALL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We were able to test the implementation using multiple CTS tests, such as
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dEQP-VK.compute.pipeline.indirect_dispatch.*&lt;/code&gt;,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dEQP-VK.pipeline.monolithic.timestamp.*&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dEQP-VK.synchronization.*&lt;/code&gt;,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dEQP-VK.query_pool.*&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dEQP-VK.multiview.*&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The userspace implementation has already landed in Mesa and the full
implementation can be checked in this
&lt;a href=&quot;https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26448&quot;&gt;MR&lt;/a&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;More about the on-going challenges in the Raspberry Pi driver stack can be
checked during this &lt;a href=&quot;https://www.youtube.com/watch?v=Gk49xj4jds4&quot;&gt;XDC 2023 talk&lt;/a&gt;
presented by Iago Toral, Juan Suárez and myself. During this talk, Iago
mentioned the CPU job work that we have been doing.&lt;/p&gt;

&lt;p&gt;Also I cannot finish this post without thanking &lt;a href=&quot;https://melissawen.github.io/&quot;&gt;Melissa
Wen&lt;/a&gt; and &lt;a href=&quot;https://blogs.igalia.com/itoral/author/itoral/&quot;&gt;Iago
Toral&lt;/a&gt; for all the help while
developing the CPU jobs for the V3D kernel driver.&lt;/p&gt;

</description>
                <pubDate>Thu, 11 Jan 2024 13:30:00 +0000</pubDate>
                <link>https://mairacanal.github.io/introducing-cpu-jobs-to-the-rpi/</link>
                <guid isPermaLink="true">https://mairacanal.github.io/introducing-cpu-jobs-to-the-rpi/</guid>
            </item>
        
            <item>
                <title>May Update: Finishing my Second Igalia CE</title>
                
                <description>&lt;p&gt;After finishing up my first &lt;a href=&quot;https://www.igalia.com/coding-experience/&quot;&gt;Igalia Coding Experience&lt;/a&gt; in January, I got the amazing opportunity to keep working in the DRI community by extending my Igalia CE to a second round.
Huge thanks to &lt;a href=&quot;https://www.igalia.com/&quot;&gt;Igalia&lt;/a&gt; for providing me with this opportunity!&lt;/p&gt;

&lt;p&gt;Another four months passed by and here I am completing another milestone with Igalia.
Previously, in the last final reports, I described GSoC as “an experience to get a better understanding of what open source is” and the first round of the Igalia CE as “an opportunity for me to mature my knowledge of technical concepts”.
My second round of the Igalia CE was a period for broadening my horizons.&lt;/p&gt;

&lt;p&gt;I had the opportunity to deepen my knowledge of a new programming language and learn more about Kernel Mode Setting (KMS).
I took my time learning more about Vulkan and the Linux graphics stack.
All of this new knowledge about the DRM infrastructure fascinated me and made me excited to keep developing.&lt;/p&gt;

&lt;p&gt;So, this is a summary report of my journey at my second Igalia CE.&lt;/p&gt;

&lt;h1 id=&quot;wrapping-up&quot;&gt;Wrapping Up&lt;/h1&gt;
&lt;hr /&gt;

&lt;p&gt;First, I took some time to wrap up the contributions of my previous Igalia CE.
In my &lt;a href=&quot;/january-update-finishing-my-igalia-ce/&quot;&gt;January Update&lt;/a&gt;, I described the journey to include IGT tests for V3D.
But at the time, I hadn’t yet sent the final versions of the tests.
Right when I started my second Igalia CE, I sent the final versions of the V3D tests, which were accepted and merged.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Series&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Status&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://patchwork.freedesktop.org/series/112363/&quot;&gt;[PATCH i-g-t 0/6] V3D Job Submission Tests&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Accepted&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://patchwork.freedesktop.org/series/112805/&quot;&gt;[PATCH i-g-t 0/3] V3D Mixed Job Submission Tests&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Accepted&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h1 id=&quot;rustgem&quot;&gt;Rustgem&lt;/h1&gt;
&lt;hr /&gt;

&lt;p&gt;The first part of my Igalia CE was focused on rewriting the VGEM driver in Rust.
VGEM (Virtual GEM Provider) is a minimal non-hardware-backed GEM (Graphics Execution Manager) service.
It is used with non-native 3D hardware for buffer sharing between the X server and DRI.&lt;/p&gt;

&lt;p&gt;The goal of the project was to explore Rust in the DRM subsystem and have a working VGEM driver written in Rust.
Rust is a blazingly fast and memory-efficient language with its powerful &lt;strong&gt;ownership model&lt;/strong&gt;.
It was really exciting to learn more about Rust and implement from the beginning a DRM driver.&lt;/p&gt;

&lt;p&gt;During the project, I wrote two blog posts describing the technical aspects of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rustgem&lt;/code&gt; driver.
If you are interested in this project, check them out!&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Date&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Blogpost&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;28th February&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;/rust-for-vgem/&quot;&gt;Rust for VGEM&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;22th March&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;/adding-timeout-rustgem/&quot;&gt;Adding a Timeout feature to Rustgem&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;By the end of the first half of the Igalia CE, I sent an RFC patch with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rustgem&lt;/code&gt; driver.
Thanks to Asahi Lina, the Rust for Linux folks, and Daniel Vetter for all the feedback provided during the development of the driver.
I still need to address some feedback and rebase the series on top of the new pin-init API, but I hope to see this driver upstream soon.
You can check the driver’s current status in this &lt;a href=&quot;https://github.com/mairacanal/linux/pull/11&quot;&gt;PR&lt;/a&gt;.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Series&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Status&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://lore.kernel.org/dri-devel/20230317121213.93991-1-mcanal@igalia.com/T/&quot;&gt;[RFC PATCH 0/9] Rust version of the VGEM driver&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;In Review&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Apart from rewriting the VGEM driver, I also sent a couple of improvements to the C version of the VGEM driver and its IGT tests.
I found a missing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mutex_destroy&lt;/code&gt; on the code and also an unused struct.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Patches&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Status&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://lore.kernel.org/dri-devel/20230202125517.427976-1-mcanal@igalia.com/T/&quot;&gt;[PATCH] drm/vgem: add missing mutex_destroy&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Accepted&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://lore.kernel.org/dri-devel/20230222160617.171429-1-mcanal@igalia.com/T/&quot;&gt;[PATCH] drm/vgem: Drop struct drm_vgem_gem_object&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Accepted&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;On the IGT side, I added some new tests to the VGEM tests.
I wanted to ensure that my driver returned the correct values for all possible error paths, so I wrote this IGT test.
Initially, it was just for me, but I decided to submit it upstream.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Series&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Status&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://patchwork.freedesktop.org/series/114912/&quot;&gt;[PATCH v3 i-g-t 0/2] Add negative tests to VGEM&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Accepted&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h1 id=&quot;virtual-kernel-mode-setting-vkms&quot;&gt;Virtual Kernel Mode Setting (VKMS)&lt;/h1&gt;
&lt;hr /&gt;

&lt;p&gt;Focusing on the VKMS was the major goal of the second part of my Igalia CE.
&lt;a href=&quot;https://melissawen.github.io/&quot;&gt;Melissa Wen&lt;/a&gt; is one of the maintainers of the VKMS, and she provided me with a fantastic opportunity to learn more about the VKMS.
So far, I haven’t dealt with displays, and learning new concepts in the graphics stack was great.&lt;/p&gt;

&lt;h2 id=&quot;rotating-planes&quot;&gt;Rotating Planes&lt;/h2&gt;

&lt;p&gt;VKMS is a software-only KMS driver that is quite useful for testing and running X (or similar compositors) on headless machines.
At the time, the driver didn’t have any support for optional plane properties, such as rotation and blend mode.
Therefore, my goal was to implement the first plane property of the driver: rotation.
I described the technicalities of this challenge in this &lt;a href=&quot;/rotating-planes-vkms/&quot;&gt;blog post&lt;/a&gt;, but I can say that it was a nice challenge of this mentorship project.&lt;/p&gt;

&lt;p&gt;In the end, we have the first plane property implemented for the VKMS and it is already committed.
Together with the VKMS part, I sent a series to the IGT mailing list with some improvements to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kms_rotation_crc&lt;/code&gt; tests.
These improvements included adding new tests for rotation with offset and reflection and the isolation of some Intel-specific tests.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Series&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Status&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://lore.kernel.org/dri-devel/20230418130525.128733-1-mcanal@igalia.com/T/&quot;&gt;[PATCH v4 0/6] drm/vkms: introduce plane rotation property&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Accepted&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://lore.kernel.org/dri-devel/20230508220030.434118-1-mcanal@igalia.com/T/&quot;&gt;[PATCH 1/2] drm/vkms: Add kernel-doc to the function vkms_compose_row()&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;In Review&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://patchwork.freedesktop.org/series/116025/&quot;&gt;[PATCH i-g-t 0/4] kms_rotation_crc improvements and generalization&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;In Review&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;improvements&quot;&gt;Improvements&lt;/h2&gt;

&lt;p&gt;As I was working with the rotation series, I discovered a couple of things that could be improved in the VKMS driver.
Last year, Igor Torrente sent a series to VKMS that changed the composition work in the driver.
Before his series, the plane composition was executed on top of the primary plane.
Now, the plane composition is executed on top of the CRTC.&lt;/p&gt;

&lt;p&gt;Although his series was merged, some parts of the code still considered that the composition was executed on top of the primary plane, limiting the VKMS capabilities.
So I sent a couple of patches to the mailing list, improving the handling of the primary plane and allowing full alpha blending on all planes.&lt;/p&gt;

&lt;p&gt;Moreover, I sent a series that added a module parameter to set a background color to the CRTC.
This work raised an interesting discussion about the need for this property by the user space and whether this parameter should be a KMS property.&lt;/p&gt;

&lt;p&gt;Apart from introducing the rotation property to the VKMS driver, I also took my time to implement two other properties: alpha and blend mode.
This series is still awaiting review, but it would be a nice addition to the VKMS, increasing its IGT test coverage rate.&lt;/p&gt;

&lt;p&gt;Finally, I found a bug in the RGB565 conversion.
The RGB565 conversion to ARGB16161616 involves some fixed-point operations and, when running the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pixel-format&lt;/code&gt; IGT test, I verified that the RGB565 test was failing.
So, some of those fixed-point operations were returning erroneous values.
I checked that the RGB coefficients weren’t being rounded when converted from fixed-point to integers.
But, this should happen in order to provided the proper coefficient values.
Therefore, the fix was: implement a new helper that rounds the fixed-point value when converting it to a integer.&lt;/p&gt;

&lt;p&gt;After performing all this work on the VKMS, I sent a patch adding myself as a VKMS maintainer, which was acked by Javier Martinez and Melissa Wen.
So now, I’m working together with Melissa, &lt;a href=&quot;https://siqueira.tech/&quot;&gt;Rodrigo Siqueira&lt;/a&gt; and all DRI community to improve and maintain the VKMS driver.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Series&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Status&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://lore.kernel.org/dri-devel/20230324164226.256084-1-mcanal@igalia.com/T/&quot;&gt;[PATCH v2 0/2] Update the handling of the primary plane&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Accepted&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://lore.kernel.org/dri-devel/20230420232228.273340-1-mcanal@igalia.com/T/&quot;&gt;[PATCH v2 1/2] drm/vkms: allow full alpha blending on all planes&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Accepted&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://lore.kernel.org/dri-devel/20230410125435.128689-1-mcanal@igalia.com/T/&quot;&gt;[PATCH v2] drm/vkms: add module parameter to set background color&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;In Review&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://lore.kernel.org/dri-devel/20230428122751.24271-1-mcanal@igalia.com/T/&quot;&gt;[PATCH] drm/vkms: Implement all blend mode properties&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;In Review&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://lore.kernel.org/dri-devel/20230512104044.65034-1-mcanal@igalia.com/T/&quot;&gt;[PATCH v3 1/2] drm: Add fixed-point helper to get rounded integer values&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Accepted&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;virtual-hardware&quot;&gt;Virtual Hardware&lt;/h2&gt;

&lt;p&gt;A couple of years ago, Sumera Priyadarsini, an Outreachy intern, worked on a Virtual Hardware functionality for the VKMS.
The idea was to add a Virtual Hardware or vblank-less mode as a kernel parameter to enable VKMS to emulate virtual devices.
This means no vertical blanking events occur and page flips are completed arbitrarily when required for updating the frame.
Unfortunately, she wasn’t able to wrap things up and this ended up never being merged into VKMS.&lt;/p&gt;

&lt;p&gt;Melissa suggested rebasing this series and now we can have the Virtual Hardware functionality working on the current VKMS.
This was a great work by Sumera and my work here was just to adapt her changes to the new VKMS code.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Series&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Status&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://lore.kernel.org/dri-devel/20230509150501.81875-1-mcanal@igalia.com/T/&quot;&gt;[PATCH 0/2] drm/vkms: Enable Virtual Hardware support&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;In Review&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;bug-fixing&quot;&gt;Bug Fixing!&lt;/h2&gt;

&lt;p&gt;Finally, I was in the last week of the project, just wrapping things up, when I decided to run the VKMS CI.
I had recently committed the rotation series and I had run the CI before, but to my surprise, I got the following output:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@fedora igt-gpu-tools]# ./build/tests/kms_writeback
IGT-Version: 1.27.1-gce51f539 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;x86_64&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;Linux: 6.3.0-rc4-01641-gb8e392245105-dirty x86_64&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;kms_writeback:1590&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; igt_kms-WARNING: Output Writeback-1 could not be assigned to a pipe
Starting subtest: writeback-pixel-formats
Subtest writeback-pixel-formats: SUCCESS &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;0.000s&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
Starting subtest: writeback-invalid-parameters
Subtest writeback-invalid-parameters: SUCCESS &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;0.001s&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
Starting subtest: writeback-fb-id
Subtest writeback-fb-id: SUCCESS &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;0.020s&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
Starting subtest: writeback-check-output
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;kms_writeback:1590&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; CRITICAL: Test assertion failure &lt;span class=&quot;k&quot;&gt;function &lt;/span&gt;get_and_wait_out_fence, file ../tests/kms_writeback.c:288:
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;kms_writeback:1590&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; CRITICAL: Failed assertion: ret &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; 0
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;kms_writeback:1590&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; CRITICAL: Last errno: 38, Function not implemented
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;kms_writeback:1590&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; CRITICAL: sync_fence_wait failed: Timer expired
Stack trace:
  &lt;span class=&quot;c&quot;&gt;#0 ../lib/igt_core.c:1963 __igt_fail_assert()&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;#1 [get_and_wait_out_fence+0x83]&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;#2 ../tests/kms_writeback.c:337 writeback_sequence()&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;#3 ../tests/kms_writeback.c:360 __igt_unique____real_main481()&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;#4 ../tests/kms_writeback.c:481 main()&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;#5 ../sysdeps/nptl/libc_start_call_main.h:74 __libc_start_call_main()&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;#6 ../csu/libc-start.c:128 __libc_start_main@@GLIBC_2.34()&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;#7 [_start+0x25]&lt;/span&gt;
Subtest writeback-check-output failed.
&lt;span class=&quot;k&quot;&gt;****&lt;/span&gt; DEBUG &lt;span class=&quot;k&quot;&gt;****&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;kms_writeback:1590&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; CRITICAL: Test assertion failure &lt;span class=&quot;k&quot;&gt;function &lt;/span&gt;get_and_wait_out_fence, file ../tests/kms_writeback.c:288:
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;kms_writeback:1590&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; CRITICAL: Failed assertion: ret &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; 0
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;kms_writeback:1590&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; CRITICAL: Last errno: 38, Function not implemented
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;kms_writeback:1590&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; CRITICAL: sync_fence_wait failed: Timer expired
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;kms_writeback:1590&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; igt_core-INFO: Stack trace:
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;kms_writeback:1590&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; igt_core-INFO:   &lt;span class=&quot;c&quot;&gt;#0 ../lib/igt_core.c:1963 __igt_fail_assert()&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;kms_writeback:1590&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; igt_core-INFO:   &lt;span class=&quot;c&quot;&gt;#1 [get_and_wait_out_fence+0x83]&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;kms_writeback:1590&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; igt_core-INFO:   &lt;span class=&quot;c&quot;&gt;#2 ../tests/kms_writeback.c:337 writeback_sequence()&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;kms_writeback:1590&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; igt_core-INFO:   &lt;span class=&quot;c&quot;&gt;#3 ../tests/kms_writeback.c:360 __igt_unique____real_main481()&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;kms_writeback:1590&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; igt_core-INFO:   &lt;span class=&quot;c&quot;&gt;#4 ../tests/kms_writeback.c:481 main()&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;kms_writeback:1590&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; igt_core-INFO:   &lt;span class=&quot;c&quot;&gt;#5 ../sysdeps/nptl/libc_start_call_main.h:74 __libc_start_call_main()&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;kms_writeback:1590&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; igt_core-INFO:   &lt;span class=&quot;c&quot;&gt;#6 ../csu/libc-start.c:128 __libc_start_main@@GLIBC_2.34()&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;kms_writeback:1590&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; igt_core-INFO:   &lt;span class=&quot;c&quot;&gt;#7 [_start+0x25]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;****&lt;/span&gt;  END  &lt;span class=&quot;k&quot;&gt;****&lt;/span&gt;
Subtest writeback-check-output: FAIL &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1.047s&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;🫠 🫠 🫠 🫠 🫠 🫠 🫠 🫠 🫠 🫠 🫠 🫠 🫠 🫠 🫠 🫠&lt;/p&gt;

&lt;p&gt;Initially, I thought I had introduced the bug with my rotation series.
Turns out, I just had made it more likely to happen.
This bug has been hidden in VKMS for a while, but it happened just on rare occasions.
Yeah, I’m talking about a race condition…
The kind of bug that just stays hidden in your code for a long while.&lt;/p&gt;

&lt;p&gt;When I started to debug, I thought it was a performance issue.
But then, I increased the timeout to 10 seconds and even then the job wouldn’t finish.
So, I thought that it could be a deadlock.
But after inspecting the DRM internal locks and the VKMS locks, it didn’t seem the case.&lt;/p&gt;

&lt;p&gt;Melissa pointed me to a hint: there was one framebuffer being leaked when removing the driver.
I discovered that it was the writeback framebuffer.
It meant that the writeback job was being queued, but it wasn’t being signaled.
So, the problem was inside the VKMS locking mechanism.&lt;/p&gt;

&lt;p&gt;After tons of GDB and ftrace, I was able to find out that the composer was being set twice without any calls to the composer worker.
I changed the internal locks a bit and I was able to run the test repeatedly for minutes!
I sent the fix for review and now I’m just waiting for a Reviewed-by.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Patches&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Status&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://lore.kernel.org/dri-devel/20230515134133.108780-1-mcanal@igalia.com/T/&quot;&gt;[PATCH] drm/vkms: Fix race-condition between the hrtimer and the atomic commit&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;In Review&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;While debugging, I found some things that could be improved in the VKMS writeback file.
So, I decided to send a series with some minor improvements to the code.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Series&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Status&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://lore.kernel.org/dri-devel/20230515135204.115393-1-mcanal@igalia.com/T/&quot;&gt;[PATCH 0/3] drm/vkms: Minor Improvements&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;In Review&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h1 id=&quot;improving-igt-tests&quot;&gt;Improving IGT tests&lt;/h1&gt;
&lt;hr /&gt;

&lt;p&gt;If you run all IGT KMS tests on the VKMS driver, you will see that some tests will fail.
That’s not what we would expect: we would expect that all tests would pass or skip.
The tests could fail due to errors in the VKMS driver or be wrong exceptions on the IGT side.
So, on the final part of my Igalia CE, I inspected a couple of IGT failures and sent fixes to address the errors.&lt;/p&gt;

&lt;h2 id=&quot;linux-kernel&quot;&gt;Linux Kernel&lt;/h2&gt;

&lt;p&gt;This patch is a revival of a series I sent in January to fix the IGT test &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kms_addfb_basic@addfb25-bad-modifier&lt;/code&gt;.
This test also failed in VC4, and I investigated the reason in January.
I sent a patch to guarantee that the test would pass and after some feedback, I came down to a dead end.
So, I left this patch aside for a while and decided to recapture it now.
Now, with this patch being merged, we can guarantee that the test  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kms_addfb_basic@addfb25-bad-modifier&lt;/code&gt; is passing for multiple drivers.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Patches&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Status&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://lore.kernel.org/dri-devel/20230412142923.136707-1-mcanal@igalia.com/T/&quot;&gt;[PATCH] drm/gem: Check for valid formats&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Accepted&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;igt&quot;&gt;IGT&lt;/h2&gt;

&lt;p&gt;On the IGT side, I sent a couple of improvements to the tests.
The failure was usually just a scenario that the test didn’t consider.
For example, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kms_plane_scaling&lt;/code&gt; test was failing in VKMS, because it didn’t consider the case in which the driver did not have the rotation property.
As VKMS didn’t use to have the rotation property, the tests were failing instead of skipping.
Therefore, I just developed a path for drivers without the rotation property for the tests to skip.&lt;/p&gt;

&lt;p&gt;I sent improvements to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kms_plane_scaling&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kms_flip&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kms_plane&lt;/code&gt; tests, making the tests pass or skip on all cases for the VKMS.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Patches&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Status&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://patchwork.freedesktop.org/patch/533643/?series=116907&amp;amp;rev=1&quot;&gt;[PATCH i-g-t] tests/kms_plane_scaling: negative tests can return -EINVAL or -ERANGE&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Accepted&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://patchwork.freedesktop.org/patch/533645/?series=116907&amp;amp;rev=1&quot;&gt;[PATCH i-g-t] tests/kms_plane_scaling: fix variable misspelling&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Accepted&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://patchwork.freedesktop.org/patch/533644/?series=116907&amp;amp;rev=1&quot;&gt;[PATCH i-g-t] tests/kms_plane_scaling: remove unused parameters&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Accepted&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://patchwork.freedesktop.org/series/117250/&quot;&gt;[PATCH i-g-t] tests/kms_plane_scaling: Only set rotation if rotation != rotate-0&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Accepted&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://patchwork.freedesktop.org/series/117246/&quot;&gt;[PATCH v2 i-g-t] tests/kms_flip: Check if is Intel device before doing all the setup&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Accepted&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://patchwork.freedesktop.org/patch/533753/&quot;&gt;[PATCH i-g-t v2] tests/kms_plane: allow pixel-format tests to run on drivers without legacy LUT&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;In Review&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;vkms-ci-list&quot;&gt;VKMS CI List&lt;/h2&gt;

&lt;p&gt;One important thing to VKMS is creating a baseline of generic KMS tests that should pass.
This way, we can test new contributions against this baseline and avoid introducing regressions in the codebase.
I sent a patch to IGT to create a testlist for the VKMS driver with all the KMS tests that must pass on the VKMS driver. This is great for maintenance, as we can run the testlist to ensure that the VKMS functionalities are preserved.&lt;/p&gt;

&lt;p&gt;With new features being introduced in VKMS, it is important to keep the test list updated.
So, I verified the test results and updated this test list during my time at the Igalia CE.
I intend to keep this list updated as long as I can.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Series&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Status&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://patchwork.freedesktop.org/series/112972/&quot;&gt;[PATCH i-g-t] tests/vkms: Create a testlist to the vkms DRM driver&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Accepted&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://patchwork.freedesktop.org/series/116316/&quot;&gt;[PATCH i-g-t 0/3] tests/vkms: Update VKMS’s testlist&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Accepted&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h1 id=&quot;acknowledgment&quot;&gt;Acknowledgment&lt;/h1&gt;
&lt;hr /&gt;
&lt;p&gt;First, I would like to thank my great mentor &lt;a href=&quot;https://melissawen.github.io/&quot;&gt;Melissa Wen&lt;/a&gt;.
Melissa and I are completing a year together as mentee and mentor and it has been an amazing journey.
Since GSoC, Melissa has been helping me by answering every single question I have and providing me with great encouragement.
I have a lot of admiration for her and I’m really grateful for having her as my mentor during the last year.&lt;/p&gt;

&lt;p&gt;Also, I would like to thank &lt;a href=&quot;https://www.igalia.com/&quot;&gt;Igalia&lt;/a&gt; for giving me this opportunity to keep working in the DRI community and learning more about this fascinating topic.
Thanks to all Igalians that helped through this journey!&lt;/p&gt;

&lt;p&gt;Moreover, I would like to thank the DRI community for reviewing my patches and giving me constructive feedback.
Especially, I would like to thank Asahi Lina, Daniel Vetter and the Rust for Linux folks for all the help with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rustgem&lt;/code&gt; driver.&lt;/p&gt;

</description>
                <pubDate>Mon, 22 May 2023 12:30:00 +0000</pubDate>
                <link>https://mairacanal.github.io/may-update-finishing-my-second-igalia-ce/</link>
                <guid isPermaLink="true">https://mairacanal.github.io/may-update-finishing-my-second-igalia-ce/</guid>
            </item>
        
            <item>
                <title>Cross-Compiling CTS for the Raspberry Pi 4</title>
                
                <description>&lt;p&gt;This blogpost was actually written partially in November/December 2022 while I was developing IGT tests for the V3D driver.
I ended up leaving it aside for a while and now, I came back and finished the last loose ends.
That’s why I’m referencing the time where I was fighting against V3D’s noop jobs.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Currently, during my &lt;a href=&quot;https://www.igalia.com/coding-experience/&quot;&gt;Igalia Coding Experience&lt;/a&gt;, I’m working on the V3D’s IGT tests and therefore, I’m dealing a lot with the Raspberry Pi 4.
During the project, I had a real struggle to design the tests for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v3d_submit_cl&lt;/code&gt; ioctl, as I was not capable of submit a proper noop job to the GPU.&lt;/p&gt;

&lt;p&gt;In order to debug the tests, my mentor &lt;a href=&quot;https://melissawen.github.io/&quot;&gt;Melissa Wen&lt;/a&gt; suggested to me to run the CTS tests to reproduce a noop job and debug it through Mesa.
I cloned the CTS repository into my Raspberry Pi 4 and I tried to compile, but my Raspberry Pi 4 went OOM.
This sent me on a journey to cross-compile CTS for the Raspberry Pi 4.
I decided to compile this journey into this blogpost.&lt;/p&gt;

&lt;p&gt;During this blogpost, I’m using a Raspbian OS with desktop 64-bit.&lt;/p&gt;

&lt;h1 id=&quot;installing-mesa&quot;&gt;Installing Mesa&lt;/h1&gt;
&lt;hr /&gt;
&lt;p&gt;First, you need to install Mesa on the Raspberry Pi 4.
I decided to compile Mesa on the Raspberry Pi 4 itself, but maybe one day, I can write a blogpost about cross-compiling Mesa.&lt;/p&gt;

&lt;h2 id=&quot;1-installing-libdrm&quot;&gt;1. Installing libdrm&lt;/h2&gt;

&lt;p&gt;Currently, the Raspbian repositories only provide &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libdrm 2.4.104&lt;/code&gt; and Mesa’s main branch needs &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libdrm &amp;gt;=2.4.109&lt;/code&gt;.
So, first, let’s install &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libdrm 2.4.109&lt;/code&gt; on the Raspberry Pi 4.&lt;/p&gt;

&lt;p&gt;First, let’s make sure that you have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;meson&lt;/code&gt; installed on your RPi4.
We will need &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;meson&lt;/code&gt; to build &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libdrm&lt;/code&gt; and Mesa.
I’m installing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;meson&lt;/code&gt; through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pip3&lt;/code&gt; because we need a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;meson&lt;/code&gt; version greater than 0.60 to build Mesa.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# On the Raspberry Pi 4&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;pip3 &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;meson
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then, you can install &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libdrm 2.4.109&lt;/code&gt; on the RPi4.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# On the Raspberry Pi 4&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;wget https://dri.freedesktop.org/libdrm/libdrm-2.4.114.tar.xz
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;tar &lt;/span&gt;xvpf libdrm-2.4.114.tar.xz
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;libdrm-2.4.114
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir &lt;/span&gt;build
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;build
&lt;span class=&quot;nv&quot;&gt;$ FLAGS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;-O2 -march=armv8-a+crc+simd -mtune=cortex-a72&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;CXXFLAGS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;-O2 -march=armv8-a+crc+simd -mtune=cortex-a72&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    meson &lt;span class=&quot;nt&quot;&gt;-Dudev&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Dvc4&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;enabled&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Dintel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;disabled&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Dvmwgfx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;disabled&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-Dradeon&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;disabled&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Damdgpu&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;disabled&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Dnouveau&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;disabled&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Dfreedreno&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;disabled&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-Dinstall-test-programs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt; ..
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;ninja &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;2-going-back-to-mesa&quot;&gt;2. Going back to Mesa&lt;/h2&gt;

&lt;p&gt;So, now let’s install Mesa.
During this blogpost, I will use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;${USER}&lt;/code&gt; as the username on the machine.
Note that, in order to run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo apt build-dep mesa&lt;/code&gt;, you will have to uncomment some &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deb-src&lt;/code&gt; on the file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/apt/sources.list&lt;/code&gt; and run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo apt update&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# On the Raspberry Pi 4&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Install Mesa&apos;s build dependencies&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt build-dep mesa

&lt;span class=&quot;c&quot;&gt;# Build and Install Mesa&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git clone https://gitlab.freedesktop.org/mesa/mesa
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;mesa
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir &lt;/span&gt;builddir
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir &lt;/span&gt;installdir
&lt;span class=&quot;nv&quot;&gt;$ CFLAGS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;-mcpu=cortex-a72&quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;CXXFLAGS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;-mcpu=cortex-a72&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    meson &lt;span class=&quot;nt&quot;&gt;-Dprefix&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/home/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;USER&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/mesa/installdir&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-D&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;platforms&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;x11 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-D&lt;/span&gt; vulkan-drivers&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;broadcom &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-D&lt;/span&gt; gallium-drivers&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;kmsro,v3d,vc4 builddir
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;builddir
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ninja
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ..
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ninja &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; builddir &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;creating-the-raspberry-pis-sysroot&quot;&gt;Creating the Raspberry Pi’s sysroot&lt;/h1&gt;
&lt;hr /&gt;
&lt;p&gt;In order to cross-compile the Raspberry Pi, you need to clone the target sysroot to the host.
For it, we are going to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rsync&lt;/code&gt;, so the host and the target need to be connected through a network.&lt;/p&gt;

&lt;h2 id=&quot;on-the-raspberry-pi-4&quot;&gt;On the Raspberry Pi 4&lt;/h2&gt;

&lt;h3 id=&quot;1-update-the-system&quot;&gt;1. Update the system&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt update
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt dist-upgrade
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;2-enable-rsync-with-elevated-rights&quot;&gt;2. Enable rsync with elevated rights&lt;/h3&gt;

&lt;p&gt;As I said before, we will be using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rsync&lt;/code&gt; command to sync files between the host and the Raspberry Pi.
For some of these files, root rights is required internally, so let’s enable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rsync&lt;/code&gt; with elevated rights.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; ALL=NOPASSWD:&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;which rsync&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;sudo tee&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--append&lt;/span&gt; /etc/sudoers
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;3-setup-important-symlinks&quot;&gt;3. Setup important symlinks&lt;/h3&gt;

&lt;p&gt;Some symbolic links are needed to make the toolchain work properly, so to create all required symbolic link reliably, this bash script is needed.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;wget https://raw.githubusercontent.com/abhiTronix/raspberry-pi-cross-compilers/master/utils/SSymlinker
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Once it is downloaded, you just need to make it executable, and then run it for each path needed.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo chmod&lt;/span&gt; +x SSymlinker
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./SSymlinker &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; /usr/include/aarch64-linux-gnu/asm &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; /usr/include
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./SSymlinker &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; /usr/include/aarch64-linux-gnu/gnu &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; /usr/include
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./SSymlinker &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; /usr/include/aarch64-linux-gnu/bits &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; /usr/include
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./SSymlinker &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; /usr/include/aarch64-linux-gnu/sys &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; /usr/include
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./SSymlinker &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; /usr/include/aarch64-linux-gnu/openssl &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; /usr/include
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./SSymlinker &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; /usr/lib/aarch64-linux-gnu/crtn.o &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; /usr/lib/crtn.o
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./SSymlinker &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; /usr/lib/aarch64-linux-gnu/crt1.o &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; /usr/lib/crt1.o
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./SSymlinker &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; /usr/lib/aarch64-linux-gnu/crti.o &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; /usr/lib/crti.o
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;on-the-host-machine&quot;&gt;On the host machine&lt;/h2&gt;

&lt;h3 id=&quot;1-setting-up-the-directory-structure&quot;&gt;1. Setting up the directory structure&lt;/h3&gt;

&lt;p&gt;First, we need to create a workspace for building CTS, where the Raspberry Pi 4 sysroot is going to be built.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo mkdir&lt;/span&gt; ~/rpi-vk
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo mkdir&lt;/span&gt; ~/rpi-vk/installdir
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo mkdir&lt;/span&gt; ~/rpi-vk/tools
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo mkdir&lt;/span&gt; ~/rpi-vk/sysroot
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo mkdir&lt;/span&gt; ~/rpi-vk/sysroot/usr
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo mkdir&lt;/span&gt; ~/rpi-vk/sysroot/usr/share
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo chown&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-R&lt;/span&gt; 1000:1000 ~/rpi-vk
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~/rpi-vk
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;2-sync-raspberry-pi-4-sysroot&quot;&gt;2. Sync Raspberry Pi 4 sysroot&lt;/h3&gt;

&lt;p&gt;Now, we need to sync up our sysroot folder with the system files from the Raspberry Pi.
We will be using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rsync&lt;/code&gt; that let us sync files from the Raspberry Pi.
To do this, enter the following commands one by one into your terminal and remember to change username and 192.168.1.47 with the IP address of your Raspberry Pi.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;rsync &lt;span class=&quot;nt&quot;&gt;-avz&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--rsync-path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;sudo rsync&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--delete&lt;/span&gt; pi@192.168.1.47:/lib sysroot
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;rsync &lt;span class=&quot;nt&quot;&gt;-avz&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--rsync-path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;sudo rsync&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--delete&lt;/span&gt; pi@192.168.1.47:/usr/include sysroot/usr
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;rsync &lt;span class=&quot;nt&quot;&gt;-avz&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--rsync-path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;sudo rsync&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--delete&lt;/span&gt; pi@192.168.1.47:/usr/lib sysroot/usr
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;rsync &lt;span class=&quot;nt&quot;&gt;-avz&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--rsync-path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;sudo rsync&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--delete&lt;/span&gt; pi@192.168.1.47:/usr/share sysroot/usr
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;rsync &lt;span class=&quot;nt&quot;&gt;-avz&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--rsync-path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;sudo rsync&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--delete&lt;/span&gt; pi@192.168.1.47:/home/&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;USER&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;/mesa/installdir installdir
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;3-fix-symbolic-links&quot;&gt;3. Fix symbolic links&lt;/h3&gt;

&lt;p&gt;The files we copied in the previous step still have symbolic links pointing to the file system on the Raspberry Pi.
So, we need to alter this, so that they become relative links from the new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sysroot&lt;/code&gt; directory on the host machine.&lt;/p&gt;

&lt;p&gt;There is a Python script available online that can help us.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;wget https://raw.githubusercontent.com/abhiTronix/rpi_rootfs/master/scripts/sysroot-relativelinks.py
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Once it is downloaded, you just need to make it executable and run it.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo chmod&lt;/span&gt; +x sysroot-relativelinks.py
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./sysroot-relativelinks.py sysroot
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;4-installing-the-raspberry-pi-64-bit-cross-compiler-toolchain&quot;&gt;4. Installing the Raspberry Pi 64-Bit Cross-Compiler Toolchain&lt;/h3&gt;

&lt;p&gt;As Raspbian OS 64-bits uses GCC 10.2.0, let’s install the proper cross-compiler toolchain on our host machine.
I’m using the toolchain provided by &lt;a href=&quot;https://github.com/abhiTronix/raspberry-pi-cross-compilers&quot;&gt;abhiTronix/raspberry-pi-cross-compilers&lt;/a&gt;, but there are many other around the web that you can use.&lt;/p&gt;

&lt;p&gt;We are going to use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tools&lt;/code&gt; folder to setup our toolchain.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~/rpi-vk/tools
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;wget https://sourceforge.net/projects/raspberry-pi-cross-compilers/files/Bonus%20Raspberry%20Pi%20GCC%2064-Bit%20Toolchains/Raspberry%20Pi%20GCC%2064-Bit%20Cross-Compiler%20Toolchains/Bullseye/GCC%2010.2.0/cross-gcc-10.2.0-pi_64.tar.gz/download
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;tar &lt;/span&gt;xvf download
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rm &lt;/span&gt;download
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;5-setting-up-wayland&quot;&gt;5. Setting up Wayland&lt;/h3&gt;

&lt;p&gt;If you run all the steps from this tutorial expect this one, you will still get some weird Wayland-related errors when cross-compiling it.
This will happen because probably the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wayland-scanner&lt;/code&gt; version from your host is different from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wayland-scanner&lt;/code&gt; version of the target.
For example, on Fedora 37, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wayland-scanner&lt;/code&gt; version is 1.21.0 and the version on the Raspberry Pi 4 is 1.18.0.&lt;/p&gt;

&lt;p&gt;In order to build Wayland, you will need the following dependencies:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;dnf &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;expat-devel xmlto
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So, let’s install the proper Wayland version on our sysroot.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;wget https://wayland.freedesktop.org/releases/wayland-1.18.0.tar.xz
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;tar &lt;/span&gt;xvf wayland-1.18.0.tar.xz
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;wayland-1.18.0
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;meson &lt;span class=&quot;nt&quot;&gt;--prefix&lt;/span&gt; ~/rpi-vk/sysroot/usr build
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ninja &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;lets-cross-compile-cts&quot;&gt;Let’s cross-compile CTS!&lt;/h1&gt;
&lt;hr /&gt;
&lt;p&gt;Now that we have the hole Raspberry Pi environment set up, we just need to create a toolchain file for CMake and its all set!
So, let’s clone the CTS repository.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git clone https://github.com/KhronosGroup/VK-GL-CTS
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;VK-GL-CTS
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To build dEQP, you need first to download sources for zlib, libpng, jsoncpp, glslang, vulkan-docs, spirv-headers, and spirv-tools.
To download sources, run:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;python3 external/fetch_sources.py
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Inside the CTS directory, we are going to create a toolchain file called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cross_compiling.cmake&lt;/code&gt; with the following contents:&lt;/p&gt;

&lt;div class=&quot;language-cmake highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;CMAKE_VERBOSE_MAKEFILE ON&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;CMAKE_SYSTEM_NAME Linux&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;CMAKE_SYSTEM_VERSION 1&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;CMAKE_SYSTEM_PROCESSOR aarch64&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Check if the sysroot and toolchain paths are correct&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;tools /home/&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;USER&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;/rpi-vk/tools/cross-pi-gcc-10.2.0-64&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;rootfs_dir $ENV{HOME}/rpi-vk/sysroot&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;CMAKE_FIND_ROOT_PATH &lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;rootfs_dir&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;CMAKE_SYSROOT &lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;rootfs_dir&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;ENV{PKG_CONFIG_PATH} &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;ENV{PKG_CONFIG_LIBDIR} &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CMAKE_SYSROOT&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/usr/lib/pkgconfig:&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CMAKE_SYSROOT&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/usr/share/pkgconfig&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;ENV{PKG_CONFIG_SYSROOT_DIR} &lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CMAKE_SYSROOT&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;CMAKE_LIBRARY_ARCHITECTURE aarch64-linux-gnu&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;CMAKE_EXE_LINKER_FLAGS &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CMAKE_EXE_LINKER_FLAGS&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; -fPIC -Wl,-rpath-link,&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CMAKE_SYSROOT&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/usr/lib/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CMAKE_LIBRARY_ARCHITECTURE&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; -L&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CMAKE_SYSROOT&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/usr/lib/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CMAKE_LIBRARY_ARCHITECTURE&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;CMAKE_C_FLAGS &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CMAKE_CXX_FLAGS&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; -fPIC -Wl,-rpath-link,&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CMAKE_SYSROOT&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/usr/lib/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CMAKE_LIBRARY_ARCHITECTURE&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; -L&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CMAKE_SYSROOT&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/usr/lib/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CMAKE_LIBRARY_ARCHITECTURE&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;CMAKE_CXX_FLAGS &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CMAKE_CXX_FLAGS&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; -fPIC -Wl,-rpath-link,&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CMAKE_SYSROOT&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/usr/lib/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CMAKE_LIBRARY_ARCHITECTURE&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; -L&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CMAKE_SYSROOT&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/usr/lib/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CMAKE_LIBRARY_ARCHITECTURE&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;WAYLAND_SCANNER &lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CMAKE_SYSROOT&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;/usr/bin/wayland-scanner&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;## Compiler Binary&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;SET&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;BIN_PREFIX &lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tools&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;/bin/aarch64-linux-gnu&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nf&quot;&gt;SET&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;CMAKE_C_COMPILER &lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BIN_PREFIX&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;-gcc&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;SET&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;CMAKE_CXX_COMPILER &lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BIN_PREFIX&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;-g++ &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;SET&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;CMAKE_LINKER &lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BIN_PREFIX&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;-ld
            CACHE STRING &lt;span class=&quot;s2&quot;&gt;&quot;Set the cross-compiler tool LD&quot;&lt;/span&gt; FORCE&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;SET&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;CMAKE_AR &lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BIN_PREFIX&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;-ar
            CACHE STRING &lt;span class=&quot;s2&quot;&gt;&quot;Set the cross-compiler tool AR&quot;&lt;/span&gt; FORCE&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;SET&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;CMAKE_NM {BIN_PREFIX}-nm
            CACHE STRING &lt;span class=&quot;s2&quot;&gt;&quot;Set the cross-compiler tool NM&quot;&lt;/span&gt; FORCE&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;SET&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;CMAKE_OBJCOPY &lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BIN_PREFIX&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;-objcopy
            CACHE STRING &lt;span class=&quot;s2&quot;&gt;&quot;Set the cross-compiler tool OBJCOPY&quot;&lt;/span&gt; FORCE&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;SET&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;CMAKE_OBJDUMP &lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BIN_PREFIX&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;-objdump
            CACHE STRING &lt;span class=&quot;s2&quot;&gt;&quot;Set the cross-compiler tool OBJDUMP&quot;&lt;/span&gt; FORCE&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;SET&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;CMAKE_RANLIB &lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BIN_PREFIX&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;-ranlib
            CACHE STRING &lt;span class=&quot;s2&quot;&gt;&quot;Set the cross-compiler tool RANLIB&quot;&lt;/span&gt; FORCE&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;SET&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;CMAKE_STRIP {BIN_PREFIX}-strip
            CACHE STRING &lt;span class=&quot;s2&quot;&gt;&quot;Set the cross-compiler tool RANLIB&quot;&lt;/span&gt; FORCE&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note that we had to specify our toolchain and also the specify the path to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wayland-scanner&lt;/code&gt;.
Now that we are all set, we can finally cross-compile CTS.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir &lt;/span&gt;build
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;build
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;cmake &lt;span class=&quot;nt&quot;&gt;-DCMAKE_BUILD_TYPE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;Debug &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;-DCMAKE_LIBRARY_PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/home/&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;USER&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;/rpi-vk/installdir/lib &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;-DCMAKE_INCLUDE_PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/home/&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;USER&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;/rpi-vk/installdir/include &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;-DCMAKE_GENERATOR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;Ninja &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;-DCMAKE_TOOLCHAIN_FILE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/home/&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;USER&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;/VK-GL-CTS/cross_compiling.cmake ..
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ninja
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, you can transfer the compiled files to the Raspberry Pi 4 and run CTS!&lt;/p&gt;

&lt;hr /&gt;
&lt;p&gt;This was a fun little challenge of my CE project and it was pretty nice to learn more about CTS.
Running CTS was also a great idea from Melissa as I was able to hexdump the contents of a noop job for the V3DV and fix my noop job on IGT.
So, now I finally have a working noop job on IGT and you can check it &lt;a href=&quot;https://patchwork.freedesktop.org/series/112363/&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Also, a huge thanks to my friend &lt;a href=&quot;https://grillo-0.github.io/blog/&quot;&gt;Arthur Grillo&lt;/a&gt; for helping me with resources about cross-compiling for the Raspberry Pi.&lt;/p&gt;
</description>
                <pubDate>Tue, 16 May 2023 12:00:00 +0000</pubDate>
                <link>https://mairacanal.github.io/cross-compiling-cts-rpi4/</link>
                <guid isPermaLink="true">https://mairacanal.github.io/cross-compiling-cts-rpi4/</guid>
            </item>
        
            <item>
                <title>Rotating Planes on VKMS</title>
                
                <description>&lt;p&gt;In my last blog post, I described a bit of my previous work on the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rustgem&lt;/code&gt; project, and after that, as I had finished the VGEM features, I sent a &lt;a href=&quot;https://lore.kernel.org/dri-devel/20230317121213.93991-1-mcanal@igalia.com/T/&quot;&gt;RFC&lt;/a&gt; to the mailing list.
Although I still need to work on some &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rustgem&lt;/code&gt; feedback, I started to explore more of the KMS (Kernel Mode Setting) and its properties.&lt;/p&gt;

&lt;p&gt;I talked to my mentor &lt;a href=&quot;https://melissawen.github.io/&quot;&gt;Melissa Wen&lt;/a&gt;, one of the VKMS maintainers, and she proposed implementing plane rotation capabilities to VKMS.
The VKMS (Virtual Kernel Mode Setting) is a software-only KMS driver that is quite useful for testing and running X (or similar compositors) on headless machines.
It sounded like a great idea, as I would like to explore a bit more of the KMS side of things.&lt;/p&gt;

&lt;h1 id=&quot;what-is-plane-rotation&quot;&gt;What is Plane Rotation?&lt;/h1&gt;
&lt;hr /&gt;
&lt;p&gt;In order to have an image on a display, we need to go through the whole Kernel Mode Setting (KMS) Display Pipeline.
The pipeline has a couple of different objects, such as framebuffers, planes, and CRTCs, and the relationship between them can be quite complicated.
If you are interested in the KMS Display Pipeline, I recommend reading the great &lt;a href=&quot;https://docs.kernel.org/gpu/drm-kms.html&quot;&gt;KMS documentation&lt;/a&gt;.
But here we are focused in only one of those abstractions, the plane.&lt;/p&gt;

&lt;p&gt;In the context of graphics processing, a plane refers to an image source that can be superimposed or blended on top of a CRTC during the scanout process.
The plane itself specifies the cropping and scaling of that image, and where it is placed on the visible area of the CRTC.
Moreover, planes may possess additional attributes that dictate pixel positioning and blending, such as rotation or Z-positioning.&lt;/p&gt;

&lt;p&gt;Rotation is an optional KMS property of the DRM plane object, which we use to specify the rotation amount in degrees in counter-clockwise direction.
The rotation is applied to the image sampled from the source rectangle, before scaling it to fit in the destination rectangle.
So, basically, the rotation property adds a rotation and a reflection step between the source and destination rectangles.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;		|*********|$$$$$$$$$|              |$$$$$$$$$|@@@@@@@@@|
		|*********|$$$$$$$$$|  ---------&amp;gt;  |$$$$$$$$$|@@@@@@@@@|
		|#########|@@@@@@@@@|     90º      |*********|#########|
		|#########|@@@@@@@@@|              |*********|#########|
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The possible rotation values are &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rotate-0&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rotate-90&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rotate-180&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rotate-270&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reflect-x&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reflect-y&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now that we understand what plane rotation is, we can think about how to implement the rotation property on VKMS.&lt;/p&gt;

&lt;h1 id=&quot;rotation-on-vkms&quot;&gt;Rotation on VKMS&lt;/h1&gt;
&lt;hr /&gt;
&lt;p&gt;VKMS has some really special driver attributes, as all its composition happens by software operations.
The rotation is usually an operation that is performed on the user-space, but the hardware can also perform it.
In order for the hardware to perform it, the driver will set some registers, change some configurations, and indicate to the hardware that the plane should be rotated.
This doesn’t happen on VKMS, as the composition is essentially a software loop.
So, we need to modify this loop to perform the rotation.&lt;/p&gt;

&lt;p&gt;First, we need a brief notion of how the composition happens in VKMS.
The composition in VKMS happens line-by-line.
Each line is represented by a staging buffer, which contains the composition for one plane, and an output buffer, which contains the composition of all planes in z-pos order.
For each line, we query an array by the first pixel of the line and go through the whole source array linearly, performing the proper pixel conversion.
The composition of the line can be summarized by:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;vkms_compose_row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line_buffer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stage_buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vkms_plane_state&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plane&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pixel_argb_u16&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;out_pixels&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stage_buffer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pixels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vkms_frame_info&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frame_info&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;plane&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frame_info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;u8&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;src_pixels&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get_packed_src_addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frame_info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;limit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;min_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;size_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;drm_rect_width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frame_info&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dst&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stage_buffer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n_pixels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;size_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;limit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;src_pixels&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;frame_info&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cpp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;plane&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pixel_read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;src_pixels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;out_pixels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here we can see that we have the line, represented by the stage buffer and the y coordinate, and the source pixels.
We read each source pixel in a linear manner, through the for-loop, and we place it on the stage buffer in the appropriate format.&lt;/p&gt;

&lt;p&gt;With that in mind, we can think that rotating a plane is a matter of changing how we read and interpret the lines.
Let’s think about the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reflect-x&lt;/code&gt; operation.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;		|*********|$$$$$$$$$|                |$$$$$$$$$|*********|
		|*********|$$$$$$$$$|  -----------&amp;gt;  |$$$$$$$$$|*********|
		|#########|@@@@@@@@@|   reflect-x    |@@@@@@@@@|#########|
		|#########|@@@@@@@@@|                |@@@@@@@@@|#########|
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Thinking that the VKMS composition happens line-by-line, we can describe the operation as a read in reverse order.
So, instead of start reading the pixels from left to right, we need to start reading the pixels from right to left.
We can implement this by getting the limit of the line and subtracting the current &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; position:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_x_position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vkms_frame_info&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frame_info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;limit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frame_info&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rotation&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DRM_MODE_REFLECT_X&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;limit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reflect-y&lt;/code&gt; operation, we need to start reading the plane from the last line, instead of reading it from the first line.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;		|*********|$$$$$$$$$|                |#########|@@@@@@@@@|
		|*********|$$$$$$$$$|  -----------&amp;gt;  |#########|@@@@@@@@@|
		|#########|@@@@@@@@@|   reflect-y    |*********|$$$$$$$$$|
		|#########|@@@@@@@@@|                |*********|$$$$$$$$$|
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This can be performed by changing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; on the external composition loop.
Similarly from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reflect-x&lt;/code&gt; case, we can get the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; limit and subtract the current &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; position.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_y_pos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vkms_frame_info&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frame_info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frame_info&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rotation&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DRM_MODE_REFLECT_Y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;drm_rect_height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frame_info&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rotated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So, to implement the rotation in VKMS, we need to change how we interpret the boundaries of the plane and read accordingly.&lt;/p&gt;

&lt;p&gt;This might seem odd because we could just rotate the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src&lt;/code&gt; rectangle by using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drm_rect_rotate&lt;/code&gt;, but this wouldn’t work as the composition in VKMS is performed line-by-line and the pixels are accessed linearly.
However, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drm_rect_rotate&lt;/code&gt; is of great help for us on the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rotate-90&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rotate-270&lt;/code&gt; cases.
Those cases demand scaling and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drm_rect_rotate&lt;/code&gt; helps us tremendously with it.
Basically, what it does is:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;		                                              |$$|@@|
		                                              |$$|@@|
		|*********|$$$$$$$$$|                         |$$|@@|
		|*********|$$$$$$$$$|  --------------------&amp;gt;  |$$|@@|
		|#########|@@@@@@@@@|   drm_rect_rotate(90)   |**|##|
		|#########|@@@@@@@@@|                         |**|##|
		                                              |**|##|
		                                              |**|##|
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drm_rect_rotate&lt;/code&gt; operation, we need to read the columns as lines and the lines as columns.
See that even for a case like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rotate-90&lt;/code&gt;, it is just a matter of changing the point of view and reading the lines differently.&lt;/p&gt;

&lt;hr /&gt;
&lt;p&gt;The complete implementation of all rotation modes is available &lt;a href=&quot;https://patchwork.freedesktop.org/series/116189/&quot;&gt;here&lt;/a&gt;.
Together with the rotation feature, I sent a patch to reduce the code repetition in the code by isolating the pixel conversion functionality.
This patch was already merged, but the rest of the series is still pending a Reviewed-by.&lt;/p&gt;

&lt;p&gt;Rotating planes on VKMS was a fun challenge of my &lt;a href=&quot;https://www.igalia.com/coding-experience/&quot;&gt;Igalia Coding Experience&lt;/a&gt; and I hope to keep working on VKMS to bring more and more features.&lt;/p&gt;
</description>
                <pubDate>Mon, 08 May 2023 00:00:00 +0000</pubDate>
                <link>https://mairacanal.github.io/rotating-planes-vkms/</link>
                <guid isPermaLink="true">https://mairacanal.github.io/rotating-planes-vkms/</guid>
            </item>
        
            <item>
                <title>Adding a Timeout feature to Rustgem</title>
                
                <description>&lt;p&gt;After my last blogpost, I kept developing the Rust version of the VGEM driver,
also known as rustgem for now. Previously, I had developed two important
features of the driver: the ability to attach a fence and the ability to signal
a fence. Still one important feature is still missing: the ability to prevent
hangs. Currently, if the fence is not signaled, the driver will simply hang. So,
we can create a callback that signals the fence when the fence is not signaled
by the user for more than 10 seconds.&lt;/p&gt;

&lt;p&gt;In order to create this callback, we need to have a Timer that will trigger it
after the specified amount of time.  Gladly, the Linux kernel provides us with a
Timer that can be set with a callback and a timeout. But, to use it in the Rust
code, we need to have a safe abstraction, that will ensure that the code is safe
under some assumptions.&lt;/p&gt;

&lt;h1 id=&quot;first-attempt-writing-a-timer-abstraction&quot;&gt;First Attempt: writing a Timer abstraction&lt;/h1&gt;
&lt;hr /&gt;

&lt;p&gt;Initially, I was developing an abstraction on my own as I checked the RfL
tree and there were no Timer abstractions available.&lt;/p&gt;

&lt;p&gt;The most important question here is “how can we guarantee access to other
objects inside the callback?”. The callback only has receives a pointer to the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;struct timer_list&lt;/code&gt; as its single argument. Naturally, we can think about using
a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;container_of&lt;/code&gt; macro. In order to make the compatibility layer between
Rust and the C callback, I decided to store the object inside the Timer. Yep, I
didn’t like that a lot, but it was the solution I came up with at the time. The
struct looked something like this:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cd&quot;&gt;/// A driver-specific Timer Object&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// # Invariants&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// timer is a valid pointer to a struct timer_list and we own a reference to it.&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;repr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UniqueTimer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TimerOps&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Inner&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;timer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;bindings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timer_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;_p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PhantomData&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Moreover, the second important question I had was “how can the user pass a
callback function to the timer?”. There were two possibilities: using a closure
and using a Trait. I decided to go through the trait path. Things would be kind
of similar if I decided to go into the closure path.&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cd&quot;&gt;/// Trait which must be implemented by driver-specific timer objects.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TimerOps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Sized&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;cd&quot;&gt;/// Type of the Inner data inside the Timer&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;cd&quot;&gt;/// Timer callback&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;timer_callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UniqueTimer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Inner&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With those two questions solved, it seems that we are all set and good to go.
So, we can create methods to initialize the timer and modify the timer’s
timeout, implement the Drop trait, and use the following callback by default:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;C&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timer_callback&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TimerOps&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Inner&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Sized&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;timer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;bindings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timer_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;crate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;container_of!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UniqueTimer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
			    &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UniqueTimer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// SAFETY: The caller is responsible for passing a valid timer_list subtype&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;timer_callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timer&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;All should work, right? Well… No, I didn’t really mention how I was allocating
memory. And let’s say I was initially allocating it wrongly and therefore, the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;container_of&lt;/code&gt; macro was pointing to the wrong memory space.&lt;/p&gt;

&lt;p&gt;Initially, I was allocating only &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;timer&lt;/code&gt; with the kernel memory allocator
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;krealloc&lt;/code&gt; and allocating the rest of the struct with Rust’s memory allocator.
By making such a mess, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;container_of&lt;/code&gt; wasn’t able to point to the right
memory address.&lt;/p&gt;

&lt;p&gt;I had to change things a bit to allocate the whole struct &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UniqueTimer&lt;/code&gt; with
the kernel’s memory allocator. However, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;krealloc&lt;/code&gt; returns a raw pointer and it
would be nice for the final user to get a raw pointer to the object. I wrapped
up inside another struct that could be dereferenced into the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UniqueTimer&lt;/code&gt;
object.&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cd&quot;&gt;/// A generic Timer Object&lt;/span&gt;
&lt;span class=&quot;cd&quot;&gt;///&lt;/span&gt;
&lt;span class=&quot;cd&quot;&gt;/// This object should be instantiated by the end user, as it holds&lt;/span&gt;
&lt;span class=&quot;cd&quot;&gt;/// a unique reference to the UniqueTimer struct. The UniqueTimer&lt;/span&gt;
&lt;span class=&quot;cd&quot;&gt;/// methods can be used through it.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Timer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TimerOps&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Inner&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UniqueTimer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TimerOps&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Inner&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Timer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;cd&quot;&gt;/// Create a timer for its first use&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nn&quot;&gt;bindings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;krealloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
                &lt;span class=&quot;nn&quot;&gt;core&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;null_mut&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
                &lt;span class=&quot;nn&quot;&gt;core&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;mem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;size_of&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UniqueTimer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
                &lt;span class=&quot;nn&quot;&gt;bindings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;GFP_KERNEL&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;bindings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__GFP_ZERO&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UniqueTimer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;// SAFETY: The pointer is valid, so pointers to members are too.&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// After this, all fields are initialized.&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nd&quot;&gt;addr_of_mut!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;nn&quot;&gt;bindings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;timer_setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;addr_of_mut!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.timer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;timer_callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And then the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;container_of&lt;/code&gt; macro started working! Now, I could setup a Timer
for each fence and keep the fence inside the timer. Finally, I could use the
fence inside the timer to signal it when it was not signaled by the user for
more than 10 seconds.&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TimerOps&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VgemFenceOps&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Inner&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UniqueFence&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;timer_callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UniqueTimer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UniqueFence&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timer&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.signal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So, I tested the driver with IGT using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vgem_slow&lt;/code&gt; test and it was now
passing! All IGT tests were passing and it looked like the driver was
practically completed (some FIXME problems notwithstanding). But, let’s see if
this abstraction is really safe…&lt;/p&gt;

&lt;h1 id=&quot;second-attempt-using-a-timer-abstraction&quot;&gt;Second Attempt: using a Timer abstraction&lt;/h1&gt;
&lt;hr /&gt;

&lt;p&gt;First, let’s inspect the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;struct timer_list&lt;/code&gt; in the C code.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timer_list&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hlist_node&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt;       &lt;span class=&quot;n&quot;&gt;expires&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timer_list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;u32&lt;/span&gt;         &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;By looking at this struct, we can see a problem in my abstraction: a timer
can point to a timer through a list. If you are not familiar with Rust, this can
seem normal, but self-referential types can lead to undefined behavior (UB).&lt;/p&gt;

&lt;p&gt;Let’s say we have an example type with two fields: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;u32&lt;/code&gt; and a pointer to this
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;u32&lt;/code&gt; value. Initially, everything looks fine, the pointer field points to the
value field in memory address A, which contains a valid &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;u32&lt;/code&gt;, and all pointers
are &lt;strong&gt;valid&lt;/strong&gt;. But Rust has the freedom to move values around memory. For
example, if we pass this struct into another function, it might get moved to a
different memory address. So, the once valid pointer is no longer valid, because
when we move the struct, the struct’s fields change their address, but not their
value. Now, the pointer fields still point to the memory address A, although the
value field is located at the memory address B now. This is really bad and can
lead to UB.&lt;/p&gt;

&lt;p&gt;The solution is to make &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;timer_list&lt;/code&gt; implement the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!Unpin&lt;/code&gt; trait. This means
that to use this type safely, we can’t use regular pointers for self-reference.
Instead, we use special pointers that “pin” their values into place, ensuring
they can’t be moved.&lt;/p&gt;

&lt;p&gt;Still looking at the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;struct timer_list&lt;/code&gt;, it is possible to notice that a timer
can queue itself in the timer function. This functionality is not covered by my
current abstraction.&lt;/p&gt;

&lt;p&gt;Moreover, I was using jiffies to modify the timeout duration and I was adding a
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Duration&lt;/code&gt; to the jiffies. This is problematic, because it can cause a data
races. Reading jiffies and adding a duration to them should be an atomic
operation.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Huge thanks to the RfL folks that pointed the errors in my implementation!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With all these problems pointed out, it is time to fix them! I could have
reimplemented my safe abstraction, but the RfL folks pointed me to a Timer
abstraction that they are developing in a &lt;a href=&quot;https://github.com/fbq/linux-rust/commits/rust-dev&quot;&gt;downstream
tree&lt;/a&gt;. Therefore, I decided
to use their Timer abstraction.&lt;/p&gt;

&lt;p&gt;There were two options to implement a Timer abstraction:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;To implement the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Timeout&lt;/code&gt; trait to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VgemFence&lt;/code&gt; struct&lt;/li&gt;
  &lt;li&gt;To use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FnTimer&lt;/code&gt; abstraction&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the end, I decided to go with the second approach. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FnTimer&lt;/code&gt; receives a
closure that will be executed at the timeout. The closure can return an enum that
indicated if the timer is done or if it should be rescheduled.&lt;/p&gt;

&lt;p&gt;When implementing the timer, I had &lt;strong&gt;a lot&lt;/strong&gt; of borrow checker problems.  See…
I need to use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Fence&lt;/code&gt; object inside the callback and also move the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Fence&lt;/code&gt;
object at the end of the function. So, I got plenty of “cannot move out of
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fence&lt;/code&gt; because it is borrowed” errors. Also, I needed the Timer to be dropped
at the same time as the fence, so I needed to store the Timer inside the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VgemFence&lt;/code&gt; struct.&lt;/p&gt;

&lt;p&gt;The solution to the problems: smart pointers! I boxed the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FnTimer&lt;/code&gt; and the closure
inside the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FnTimer&lt;/code&gt; so that I could store it inside the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VgemFence&lt;/code&gt; struct.
Then, the second problem got fixed. But, I still cannot use the fence inside the
closure, because it wasn’t encapsulated inside a smart pointer. So, I used an
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Arc&lt;/code&gt; to box &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Fence&lt;/code&gt;, clone it, and move it to the scope of the closure.&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;crate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VgemFence&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;fence&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Arc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UniqueFence&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Fence&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;_timer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Box&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FnTimer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Box&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;dyn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;FnMut&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Next&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Sync&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VgemFence&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;crate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fence_ctx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;FenceContexts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QUEUE_NAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QUEUE_CLASS_KEY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fence&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Arc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;try_new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fence_ctx&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.new_fence&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Fence&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{})&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;c1&quot;&gt;// SAFETY: The caller calls [`FnTimer::init_timer`] before using the timer.&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Box&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;try_new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;nn&quot;&gt;FnTimer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Box&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;try_new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
				&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fence&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fence&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.clone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
				&lt;span class=&quot;k&quot;&gt;move&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
					&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fence&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.signal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
					&lt;span class=&quot;nf&quot;&gt;Ok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Done&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
				&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
			&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Box&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;c1&quot;&gt;// SAFETY: As FnTimer is inside a Box, it won&apos;t be moved.&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;core&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;pin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Pin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new_unchecked&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

		&lt;span class=&quot;nd&quot;&gt;timer_init!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;vgem_timer&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

		&lt;span class=&quot;c1&quot;&gt;// SAFETY: Duration.as_millis() returns a valid total number of whole milliseconds.&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timeout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
			&lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;bindings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;msecs_to_jiffies&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Duration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;from_secs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.as_millis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.try_into&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

		&lt;span class=&quot;c1&quot;&gt;// We force the fence to expire within 10s to prevent driver hangs&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.raw_timer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.schedule_at&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;jiffies_later&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;

		&lt;span class=&quot;nf&quot;&gt;Ok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fence&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_timer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can observe in this code that the initialization of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FnTimer&lt;/code&gt; uses an
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unsafe&lt;/code&gt; operation. This happens because we still don’t have &lt;a href=&quot;https://y86-dev.github.io/blog/safe-pinned-initialization/overview.html&quot;&gt;Safe Pinned
Initialization&lt;/a&gt;.
But the RfL folks are working hard to land this feature and improve ergonomics
when using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Pin&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now, running again the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vgem_slow&lt;/code&gt; IGT test, you can see that all IGT tests are
now passing!&lt;/p&gt;

&lt;h1 id=&quot;next-steps&quot;&gt;Next Steps&lt;/h1&gt;
&lt;hr /&gt;

&lt;p&gt;During this time, many improvements landed in the driver: all the objects are
being properly dropped, including the DRM device; all error cases are returning
the correct error; the SAFETY comments are properly written and most importantly,
the timeout feature was introduced. With that, all IGT tests are passing and the
driver is functional!&lt;/p&gt;

&lt;p&gt;Now, the driver is in a good shape, apart from one FIXME problem: currently, the
IOCTL abstraction doesn’t support any drivers that the IOCTLs don’t start in
0x00 and the VGEM driver starts its IOCTLs with 0x01. I don’t know yet how to
bypass this problem without adding a dummy IOCTL as 0x00, but I hope to get a
solution to it soon.&lt;/p&gt;

&lt;p&gt;The progress of this project can be followed in this
&lt;a href=&quot;https://github.com/mairacanal/linux/pull/11&quot;&gt;PR&lt;/a&gt; and I hope to see this project
being integrated upstream in the future.&lt;/p&gt;
</description>
                <pubDate>Wed, 22 Mar 2023 00:00:00 +0000</pubDate>
                <link>https://mairacanal.github.io/adding-timeout-rustgem/</link>
                <guid isPermaLink="true">https://mairacanal.github.io/adding-timeout-rustgem/</guid>
            </item>
        
            <item>
                <title>Rust for VGEM</title>
                
                <description>&lt;p&gt;In the last blog post, I pointed out that I didn’t know exactly what it would be
my next steps for the near future. Gladly, I had the amazing opportunity to
start a new &lt;a href=&quot;https://www.igalia.com/coding-experience/&quot;&gt;Igalia Coding
Experience&lt;/a&gt; with a new project.&lt;/p&gt;

&lt;p&gt;This time &lt;a href=&quot;https://melissawen.github.io/&quot;&gt;Melissa Wen&lt;/a&gt; pitched me with the idea
to play around with Rust for Linux in order to rewrite the VGEM driver in Rust.
The Rust for Linux project is growing fast with new bindings and abstractions
being introduced in the downstream RfL kernel. Also, some basic functionalities
were introduced in Linux 6.1. Therefore, it seems like a great timing to start
exploring Rust in the DRM subsystem!&lt;/p&gt;

&lt;h1 id=&quot;why-rust&quot;&gt;Why Rust?&lt;/h1&gt;
&lt;hr /&gt;
&lt;p&gt;As mentioned by the Rust website, using Rust means &lt;strong&gt;Performance&lt;/strong&gt;,
&lt;strong&gt;Reliability&lt;/strong&gt;, and &lt;strong&gt;Productivity&lt;/strong&gt;. Rust is a blazingly fast and
memory-efficient language with its powerful &lt;strong&gt;ownership model&lt;/strong&gt;. No more looking
for use-after-free and memory leaks, as Rust guarantees memory safety and thread
safety, eliminating a handful of bugs at compile-time.&lt;/p&gt;

&lt;p&gt;Moreover, Rust provides a new way of programming. The language provides
beautiful features such as traits, enums, and error handling, that can
make us feel empowered by the language. We can use a lot of concepts from
functional programming and mix them with concepts from OOP, for example.&lt;/p&gt;

&lt;p&gt;Although I’m an absolute beginner in Rust, I can see the major advantages of the
Rust programming language. From the start, it was a bit tough to enjoy the
language, as I was fighting with the compiler most of the time. But now that I
have a more firm foundation on Rust, it is possible to appreciate the beauty in
Rust and I don’t see myself starting a new project in C++ for a long while.&lt;/p&gt;

&lt;p&gt;Bringing Rust to the Linux Kernel is a ambitious idea, but it can lead to
great changes. We can think about a world where no developers are looking for
memory leaks and use-after-free bugs due to the safety that Rust can provide us.&lt;/p&gt;

&lt;h1 id=&quot;rust-on-drm&quot;&gt;Rust on DRM&lt;/h1&gt;
&lt;hr /&gt;
&lt;p&gt;Now, what about Rust for DRM? I mean, I’m not the first one to think about it.
&lt;a href=&quot;https://twitter.com/LinaAsahi&quot;&gt;Asahi Lina&lt;/a&gt; is making a fantastic work on the
Apple M1 GPU and things are moving quite fast there. She already had great safe
abstractions for the DRM bindings and provides us the very basis for anyone who
is willing to start a new DRM driver in Rust, which is my case.&lt;/p&gt;

&lt;p&gt;That said, why not make use of Lina’s excellent bindings to build a new driver?&lt;/p&gt;

&lt;h1 id=&quot;rust-for-vgem&quot;&gt;Rust for VGEM&lt;/h1&gt;
&lt;hr /&gt;
&lt;p&gt;VGEM (Virtual GEM Provider) is a minimal non-hardware backed GEM (Graphics
Execution Manager) service. It is used with non-native 3D hardware for buffer
sharing between the X server and DRI. It is a fairly simple driver with about
400 lines of code and it uses the DMA Fence API to handle attaching and
signaling the fences.&lt;/p&gt;

&lt;p&gt;So, to rewrite VGEM in Rust, some bindings are needed, e.g. bindings for
platform device, for XArray, and for dealing with DMA fence and DMA
reservations. Furthermore, many DRM abstractions are needed as well.&lt;/p&gt;

&lt;p&gt;In this sense, a lot of the DRM abstractions are already developed by Lina and
also she is developing abstractions for DMA fence. So, in this project, I’ll be
focusing on the bindings that Lina and the RfL folks haven’t developed yet.&lt;/p&gt;

&lt;p&gt;After developing the bindings, it is a matter of developing the driver, which
it’ll be quite simple after all DMA abstractions are set, because most of the
driver consists of fence manipulation.&lt;/p&gt;

&lt;h1 id=&quot;current-status&quot;&gt;Current Status&lt;/h1&gt;
&lt;hr /&gt;
&lt;p&gt;I have developed the main platform device registration of the driver. As VGEM is
a virtual device, the standard probe initialization is not useful, as a virtual
device cannot be probed by the pseudo-bus that holds the platform devices. So,
as VGEM is not a usual hotplugged device, we need to use the legacy platform
device initialization. This made me develop my first binding for legacy
registration:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cd&quot;&gt;/// Add a platform-level device and its resources&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CStr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pdev&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;from_kernel_err_ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;nn&quot;&gt;bindings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;platform_device_register_simple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.as_char_ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
			&lt;span class=&quot;nn&quot;&gt;core&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;nf&quot;&gt;Ok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pdev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;used_resource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;is_registered&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For sure, the registration must follow the unregistration of the device, so I
implemented a Drop trait for the struct Device in order to guarantee the proper
device removal without explicitly calling it.&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Drop&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Device&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;drop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.is_registered&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;c1&quot;&gt;// SAFETY: This path only runs if a previous call to `register`&lt;/span&gt;
			&lt;span class=&quot;c1&quot;&gt;// completed successfully.&lt;/span&gt;
			&lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;bindings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;platform_device_unregister&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
		&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After those, I also developed bindings for a couple of more functions and
together with Lina’s bindings, I could initialize the platform device and
register the DRM device under a DRM minor!&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[   38.825684] vgem: vgem_init: platform_device with id -1
[   38.826505] [drm] Initialized vgem 1.0.0 20230201 for vgem on minor 0
[   38.858230] vgem: Opening...
[   38.862377] vgem: Closing...
[   41.543416] vgem: vgem_exit: drop
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Next, I focused on the development of the two IOCTLs: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drm_vgem_fence_attach&lt;/code&gt;
and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drm_vgem_fence_signal&lt;/code&gt;. The first is responsable for creating and attaching
a fence to the VGEM handle, while the second signals and consumes a fence
earlier attached to a VGEM handle.&lt;/p&gt;

&lt;p&gt;In order to add a fence, bindings to DMA reservation are needed. So, I started
by creating a safe abstraction for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;struct dma_resv&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cd&quot;&gt;/// A generic DMA Resv Object&lt;/span&gt;
&lt;span class=&quot;cd&quot;&gt;///&lt;/span&gt;
&lt;span class=&quot;cd&quot;&gt;/// # Invariants&lt;/span&gt;
&lt;span class=&quot;cd&quot;&gt;/// ptr is a valid pointer to a dma_resv and we own a reference to it.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DmaResv&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;bindings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dma_resv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DmaResv&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
	
    &lt;span class=&quot;cd&quot;&gt;/// Add a fence to the dma_resv object&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;add_fences&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;fence&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;dyn&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RawDmaFence&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;num_fences&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;usage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;bindings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dma_resv_usage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Result&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;bindings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;dma_resv_lock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;core&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;null_mut&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.reserve_fences&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num_fences&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nf&quot;&gt;Ok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;c1&quot;&gt;// SAFETY: ptr is locked with dma_resv_lock(), and dma_resv_reserve_fences()&lt;/span&gt;
                &lt;span class=&quot;c1&quot;&gt;// has been called.&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;nn&quot;&gt;bindings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;dma_resv_add_fence&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fence&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.raw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;usage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;nf&quot;&gt;Err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        
        &lt;span class=&quot;k&quot;&gt;unsafe&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;bindings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;dma_resv_unlock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With that step, I could simply write the IOCTLs based on the new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DmaResv&lt;/code&gt;
abstraction and Lina’s fence abstractions.&lt;/p&gt;

&lt;p&gt;To test the IOCTLs, I used some already available IGT tests: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dmabuf_sync_file&lt;/code&gt;
and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vgem_basic&lt;/code&gt;. Those tests use VGEM as it base, so if the tests pass, it
means that the IOCTLs are working properly. And, after some debugging and rework
in the IOCTLs, I managed to get most of the tests to pass!&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[root@fedora igt-gpu-tools]# ./build/tests/dmabuf_sync_file
IGT-Version: 1.27-gaa16e812 (x86_64) (Linux: 6.2.0-rc3-asahi-02441-g6c8eda039cfb-dirty x86_64)
Starting subtest: export-basic
Subtest export-basic: SUCCESS (0.000s)
Starting subtest: export-before-signal
Subtest export-before-signal: SUCCESS (0.000s)
Starting subtest: export-multiwait
Subtest export-multiwait: SUCCESS (0.000s)
Starting subtest: export-wait-after-attach
Subtest export-wait-after-attach: SUCCESS (0.000s)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can check out the current progress of this project on this
&lt;a href=&quot;https://github.com/mairacanal/linux/pull/11&quot;&gt;pull request&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;next-steps&quot;&gt;Next Steps&lt;/h1&gt;
&lt;hr /&gt;
&lt;p&gt;Although most of the IGT tests are now passing, two tests aren’t working yet:
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vgem_slow&lt;/code&gt;, as I haven’t introduced the timeout yet, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vgem_basic@unload&lt;/code&gt;,
as I still need to debug why the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Drop&lt;/code&gt; trait from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drm::drv::Registration&lt;/code&gt; is
not being called.&lt;/p&gt;

&lt;p&gt;After bypassing those two problems, I still need to rework some of my code, as,
for example, I’m using a dummy IOCTL as IOCTL number 0x00, as the current macro
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kernel::declare_drm_ioctl&lt;/code&gt; doesn’t support any drivers for which the IOCTL doesn’t
start in 0x00.&lt;/p&gt;

&lt;p&gt;So, there is a lot of work yet to be done!&lt;/p&gt;
</description>
                <pubDate>Tue, 28 Feb 2023 00:00:00 +0000</pubDate>
                <link>https://mairacanal.github.io/rust-for-vgem/</link>
                <guid isPermaLink="true">https://mairacanal.github.io/rust-for-vgem/</guid>
            </item>
        
            <item>
                <title>January Update: Finishing my Igalia CE</title>
                
                <description>&lt;p&gt;2022 really passed by fast and after I completed the GSoC 2022, I’m now
completing another milestone: my project in the &lt;a href=&quot;https://www.igalia.com/coding-experience/&quot;&gt;Igalia Coding
Experience&lt;/a&gt; and I
had the best experience during those four months. I learned tremendously about
the Linux graphics stack and now I can say for sure that I would love to keep
working in the DRM community.&lt;/p&gt;

&lt;p&gt;While GSoC was, for me, an experience to get a better understanding of what open
source is, Igalia CE was an opportunity for me to mature my knowledge of
technical concepts.&lt;/p&gt;

&lt;p&gt;So, this is a summary report of my journey at the Igalia CE.&lt;/p&gt;

&lt;h1 id=&quot;igt-tests-to-v3d&quot;&gt;&lt;a href=&quot;https://gitlab.freedesktop.org/drm/igt-gpu-tools&quot;&gt;IGT&lt;/a&gt; tests to V3D&lt;/h1&gt;
&lt;hr /&gt;

&lt;p&gt;Initially, V3D only had three basic IGT tests: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v3d_get_bo_offset&lt;/code&gt;,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v3d_get_param&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v3d_mmap&lt;/code&gt;. So, the basic goal of my CE project was to add
more tests to the V3D driver.&lt;/p&gt;

&lt;p&gt;V3D is the driver that supports the Broadcom V3D 3.3 and 4.1 OpenGL ES GPUs, and
is the driver that provides 3D rendering to the Raspberry Pi 4. V3D is composed
of a tiled renderer, a TFU (Texture Formatting Unit), and a CSD (Compute Shader
Dispatch).&lt;/p&gt;

&lt;p&gt;During the CE, I was able to develop tests for almost all eleven V3D ioctls
(except &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v3d_submit_tfu&lt;/code&gt;). I began writing tests to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v3d_create_bo&lt;/code&gt; ioctl
and &lt;em&gt;Performance Monitor&lt;/em&gt; (perfmon) related ioctls. I developed tests that check
the basic functionality of the ioctls and I inspected the kernel code to
understand situations where the ioctl should fail.&lt;/p&gt;

&lt;p&gt;After those tests, I got the biggest challenge that I had on my CE project:
performing a Mesa’s no-op job on IGT. A no-op job is one of the simplest jobs
that can be submitted to the V3D. It is a 3D rendering job, so it is a job
submitted through the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v3d_submit_cl&lt;/code&gt; ioctl, and performing this job on IGT was
fundamental to developing good tests for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v3d_submit_cl&lt;/code&gt; ioctl.&lt;/p&gt;

&lt;p&gt;The main problem I faced on submitting a no-op job on IGT was: I would copy many
and many Mesa files to IGT. And I took a while fighting against this idea,
looking for other ways to submit a job to V3D. But, as some experience developers
pointed out, packeting is the best option for it. So indeed, the final solution
I came in with was to copy a couple of files from Mesa, but just three of them,
which sounds reasonable.&lt;/p&gt;

&lt;p&gt;So, after some time, I was able to bring the Mesa structure to IGT with minimal
overhead. But, I was still not able to run a successful no-op job as the job’s
fence wasn’t being signaled by the end of the job. Then, Melissa Wen guided me
to experiment running CTS tests to inspect the no-op job. With the CTS tests, I
was able to hexdump the contents of the packet and understand what was going on
wrong in my no-op job.&lt;/p&gt;

&lt;p&gt;Running the CTS in the Raspberry Pi 4 was a fun side-quest of the project and
ended up resulting in a commit to the CTS repository, as CTS wasn’t handling
appropriately the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wayland-scanner&lt;/code&gt; for cross-compiling. CTS was picking the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wayland-scanner&lt;/code&gt; from the host computer instead of picking the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wayland-scanner&lt;/code&gt; executable available in the target sysroot. This was fixed
with this simple patch:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/KhronosGroup/VK-GL-CTS/commit/6dfa0b69b46e69bdabd213ec2cf915bcd6e689f3&quot;&gt;&lt;strong&gt;Allow override of wayland_scanner executable&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When I finally got a successful no-op job, I was able to write the tests for the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v3d_submit_cl&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v3d_wait_bo&lt;/code&gt; ioctls. On these tests, I tested primarily job
synchronization with single syncobjs and multiple syncobjs. In this part of the
project, I had the opportunity to learn a lot about syncobjs and different forms
of synchronization in the kernel and userspace.&lt;/p&gt;

&lt;p&gt;Having done the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v3d_submit_cl&lt;/code&gt; tests, I developed the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v3d_submit_csd&lt;/code&gt; tests in
a similar way, as the job submission process is kind of similar. For submitting
a CSD job, it is necessary to make a valid submission with a pipeline assembly
shader and as IGT doesn’t have a shader compiler, so I hard-coded the assembly
of an empty shader in the code. In this way, I was able to get a simple CSD job
submitted, and having done that, I could now play around with mixing CSD and CL
jobs.&lt;/p&gt;

&lt;p&gt;In these tests, I could test the synchronization between two job queues and see,
for example, if they were proceeding independently.&lt;/p&gt;

&lt;p&gt;So, by the end of the review process, I will add 66 new sub-tests to V3D, having
in total 72 IGT sub-tests! Those tests are checking invalid parameters,
synchronization, and the proper behavior of the functionalities.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Patch/Series&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Status&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://patchwork.freedesktop.org/series/110681/&quot;&gt;[PATCH 0/7] V3D IGT Tests Updates&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Accepted&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://patchwork.freedesktop.org/series/112215/&quot;&gt;[PATCH 0/2] Tests for V3D/VC4 Mmap BO IOCTLs&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Accepted&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://patchwork.freedesktop.org/series/112370/&quot;&gt;[PATCH 0/4] Make sure v3d/vc4 support performance monitor&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;In Review&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://patchwork.freedesktop.org/series/112363/&quot;&gt;[PATCH 0/6] V3D Job Submission Tests&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;In Review&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://patchwork.freedesktop.org/series/112805/&quot;&gt;[PATCH 0/3] V3D Mixed Job Submission Tests&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;In Review&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;mesa&quot;&gt;&lt;a href=&quot;https://gitlab.freedesktop.org/mesa/mesa&quot;&gt;Mesa&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;Apart from reading a lot of kernel code, I also started to explore some of the
Mesa code, especially the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v3dv&lt;/code&gt; driver. On Mesa, I was trying to understand the
userspace use of the ioctls in order to create useful tests. While I was
exploring the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v3dv&lt;/code&gt;, I was able to make two very simple contributions to Mesa:
fixing typos and initializing a variable in order to assure proper error
handling.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Patch&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Status&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://gitlab.freedesktop.org/mesa/mesa/-/commit/d34f3a1db594c778e0c6bae7a5798742edb9635d&quot;&gt;v3dv: fix multiple typos&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Accepted&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://gitlab.freedesktop.org/mesa/mesa/-/commit/a2252adde8235d5c4d78d9347527cd7914bb905a&quot;&gt;v3dv: initialize fd variable for proper error handling&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Accepted&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h1 id=&quot;igt-tests-to-vc4&quot;&gt;&lt;a href=&quot;https://gitlab.freedesktop.org/drm/igt-gpu-tools&quot;&gt;IGT&lt;/a&gt; tests to VC4&lt;/h1&gt;
&lt;hr /&gt;

&lt;p&gt;VC4 and V3D share some similarities in their basic 3D rendering implementation.
VC4 contains a 3D engine, and a display output pipeline that supports different
outputs. The display part of the VC4 is used on the Raspberry Pi 4 together with
the V3D driver.&lt;/p&gt;

&lt;p&gt;Although my main focus was on the V3D tests, as the VC4 and V3D drivers are kind
of similar, I was able to bring some improvements to the VC4 tests as well. I
added tests for perfmons and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vc4_mmap&lt;/code&gt; ioctl and improved a couple of
things in the tests, such as moving it a separate folder and creating a check to
skip the VC4 tests if they are running on a Raspberry Pi 4.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Patch/Series&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Status&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://patchwork.freedesktop.org/series/110948/&quot;&gt;[PATCH 0/5] VC4 IGT Tests Updates&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Accepted&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://patchwork.freedesktop.org/series/112215/&quot;&gt;[PATCH 0/2] Tests for V3D/VC4 Mmap BO IOCTLs&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Accepted&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://patchwork.freedesktop.org/series/112370/&quot;&gt;[PATCH 0/4] Make sure v3d/vc4 support performance monitor&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;In Review&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://patchwork.freedesktop.org/patch/516737/&quot;&gt;tests/vc4_purgeable_bo: Fix conditional assertion&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;In Review&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h1 id=&quot;linux-kernel&quot;&gt;&lt;a href=&quot;https://cgit.freedesktop.org/drm/drm-misc/&quot;&gt;Linux Kernel&lt;/a&gt;&lt;/h1&gt;
&lt;hr /&gt;

&lt;h2 id=&quot;v3dvc4-drivers&quot;&gt;V3D/VC4 drivers&lt;/h2&gt;

&lt;p&gt;During this process of writing tests to IGT, I ended up reading a lot of kernel
code from V3D in order to evaluate possible userspace scenarios. While
inspecting some of the V3D code, I could find a couple of small things that
could be improved, such as using the DRM-managed API for mutexes and replacing
open-coded implementations with their DRM counterparts.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Patch&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Status&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://patchwork.freedesktop.org/series/110634/&quot;&gt;drm/v3d: switch to drmm_mutex_init&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Accepted&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://patchwork.freedesktop.org/series/110634/&quot;&gt;drm/v3d: add missing mutex_destroy&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Accepted&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://patchwork.freedesktop.org/series/112257/&quot;&gt;drm/v3d: replace open-coded implementation of drm_gem_object_lookup&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Accepted&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Although I didn’t explore the VC4 driver as much as the V3D driver, I also took
a look at the driver, and I was able to detect a small thing that could be
improved: using the DRM-core helpers instead of open-code. Moreover, after a
report on the mailing list, I bisected a deadlock and I was able to fix it after
some study about the KMS locking system.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Patch&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Status&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://patchwork.freedesktop.org/series/112299/&quot;&gt;drm/vc4: drop all currently held locks if deadlock happens&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Accepted&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://patchwork.freedesktop.org/patch/516491/?series=112347&amp;amp;rev=1&quot;&gt;drm/vc4: replace drm_gem_dma_object for drm_gem_object in vc4_exec_info&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;In Review&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://patchwork.freedesktop.org/patch/516490/?series=112347&amp;amp;rev=1&quot;&gt;drm/vc4: replace obj lookup steps with drm_gem_objects_lookup&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;In Review&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;the-debugfs-side-quest&quot;&gt;The debugfs side-quest&lt;/h2&gt;

&lt;p&gt;The debugfs side-quest was a total coincidence during this project. I had some
spare time and was looking for something to develop. While looking at the DRM
TODO list, I bumped into the debugfs clean-up task and found it interesting to
work on. So, I started to work on this task based on the previous work from
Wambui Karuga, who was a Outreachy mentee and worked on this feature during her
internship. By chance, when I talked to Melissa about it, she told me that she
had knowledge of this project due to a past Outreachy internship that she was
engaged on, and she was able to help me figure out the last pieces of
this side-quest.&lt;/p&gt;

&lt;p&gt;After submitting the first patch, introducing the debugfs device-centered
functions, and converting a couple of drivers to the new structure, I decided to
remove the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;debugfs_init&lt;/code&gt; hook from a couple of drivers in order to get closer
to the goal of removing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;debugfs_init&lt;/code&gt; hook. Moreover, during my last week
in the CE, I tried to write a debugfs infrastructure for the KMS objects, which
was another task in the TODO list, although I still need to do some rework on
this series.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Patch/Series&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Status&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://patchwork.freedesktop.org/series/111216/&quot;&gt;[PATCH 0/7] Introduce debugfs device-centered functions&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Accepted&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://patchwork.freedesktop.org/patch/517186/?series=112451&amp;amp;rev=1&quot;&gt;drm/debugfs: use octal permissions instead of symbolic permissions&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Accepted&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://patchwork.freedesktop.org/patch/517185/?series=112451&amp;amp;rev=1&quot;&gt;drm/debugfs: add descriptions to struct parameters&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Accepted&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://patchwork.freedesktop.org/series/112233/&quot;&gt;[PATCH 0/7] Convert drivers to the new debugfs device-centered functions&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Accepted&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://patchwork.freedesktop.org/series/112684/&quot;&gt;[PATCH 0/13] drm/debugfs: Create a debugfs infrastructure for kms objects&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;In Review&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;more-side-quests&quot;&gt;More side-quests&lt;/h2&gt;

&lt;p&gt;By the end of the CE, I was on my summer break from university, so I had some
time to take a couple of side-quests in this journey.&lt;/p&gt;

&lt;p&gt;The first side-quest that I got into originated in a failed IGT test on the VC4,
the “addfb25-bad-modifier” IGT test. Initially, I proposed a fix only for the
VC4, but after some discussion in the mailing list, I decided to move forward
with the idea to create the check for valid modifiers in the DRM core. The
series is still in review, but I had some great interactions during the
iterations.&lt;/p&gt;

&lt;p&gt;The second side-quest was to understand why the IGT test &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kms_writeback&lt;/code&gt; was
causing a kernel oops in vkms. After some bisecting and some study about KMS’s
atomic API, I was able to detect the problem and write a solution for it. It was
pretty exciting to deal with vkms for the first time and to get some notion
about the display side of things.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Patch/Series&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Status&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://patchwork.freedesktop.org/patch/505760/?series=109345&amp;amp;rev=1&quot;&gt;drm/tests: Split drm_test_dp_mst_calc_pbn_mode into parameterized tests&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Accepted&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://patchwork.freedesktop.org/patch/505761/?series=109345&amp;amp;rev=1&quot;&gt;drm/tests: Split drm_test_dp_mst_sideband_msg_req_decode into parameterized tests&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Accepted&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://patchwork.freedesktop.org/series/516047/&quot;&gt;tests/kms_addfb_basic: Avoid open-coded expressions&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Accepted&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://patchwork.freedesktop.org/series/112546/&quot;&gt;[PATCH 0/3] Check for valid framebuffer’s format&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;In Review&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://patchwork.freedesktop.org/series/112487/&quot;&gt;drm/vkms: reintroduce prepare_fb and cleanup_fb functions&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Accepted&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h1 id=&quot;next-steps&quot;&gt;Next Steps&lt;/h1&gt;
&lt;hr /&gt;

&lt;p&gt;A bit different from the end of GSoC, I’m not really sure what are going to be
my next steps in the next couple of months. The only thing I know for sure is
that I will keep contributing to the DRM subsystem and studying more about DRI,
especially the 3D rendering and KMS.&lt;/p&gt;

&lt;p&gt;The DRI infrastructure is really fascinating and there is so much to be learn!
Although I feel that I improved a lot in the last couple of months, I still feel
like a newbie in the community. I still want to have more knowledge of the DRM
core helpers and understand how everything glues together.&lt;/p&gt;

&lt;p&gt;Apart from the DRM subsystem, I’m also trying to take some time to program more
in Rust and maybe contribute to other open-source projects, like Mesa.&lt;/p&gt;

&lt;h1 id=&quot;acknowledgment&quot;&gt;Acknowledgment&lt;/h1&gt;
&lt;hr /&gt;

&lt;p&gt;I would like to thank my great mentors &lt;a href=&quot;https://melissawen.github.io/&quot;&gt;Melissa
Wen&lt;/a&gt; and &lt;a href=&quot;https://andrealmeid.com/&quot;&gt;André
Almeida&lt;/a&gt; for helping me through this journey. I
wouldn’t be able to develop this project without their great support and
encouragement. They were an amazing duo of mentors and I thank them for
answering all my questions and helping me with all the challenges.&lt;/p&gt;

&lt;p&gt;Also, I would like to thank the DRI community for reviewing my patches and
giving me constructive feedback. Especially, I would like to thank Daniel Vetter
for answering patiently every single question that I had about the debugfs
clean-up and to thank Jani Nikula, Maxime Ripard, Thomas Zimmermann, Javier
Martinez Canillas, Emma Anholt, Simon Ser, Iago Toral, Kamil Konieczny and
many others that took their time to review my patches, answer my questions and
provide me constructive feedback.&lt;/p&gt;
</description>
                <pubDate>Tue, 17 Jan 2023 00:00:00 +0000</pubDate>
                <link>https://mairacanal.github.io/january-update-finishing-my-igalia-ce/</link>
                <guid isPermaLink="true">https://mairacanal.github.io/january-update-finishing-my-igalia-ce/</guid>
            </item>
        
            <item>
                <title>November Update: Exploring V3D</title>
                
                <description>&lt;p&gt;It has been a busy couple of months. As I pointed on my last blog post, I finished GSoC and joined the &lt;a href=&quot;https://www.igalia.com/coding-experience/&quot;&gt;Igalia Coding Experience&lt;/a&gt; mentorship project. In October, I also traveled to Minneapolis for XDC 2022 where I presented to the Linux Graphics community our AMD/KUnit work with my colleagues. So, let’s make a summary of the last couple of months.&lt;/p&gt;

&lt;h1 id=&quot;xdc-2022&quot;&gt;XDC 2022&lt;/h1&gt;

&lt;hr /&gt;

&lt;p&gt;Just a small thank you note to X.Org Foundation for sponsoring my travel to Minneapolis. XDC 2022 was a great experience, and I learned quite a lot during the talks. Although I was a newcomer, all developers were very nice to me, and it was great to talk to experienced developers (and meet my mentors in person). Also, I presented the GSoC/XOrg work on the first day of the conference and this talk is available on &lt;a href=&quot;https://www.youtube.com/watch?v=nbRbM-Ld-44&amp;amp;t=3s&amp;amp;pp=ugMICgJwdBABGAE%3D&quot;&gt;YouTube&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;working-with-the-raspberry-pi-4&quot;&gt;Working with the Raspberry Pi 4&lt;/h1&gt;

&lt;hr /&gt;

&lt;p&gt;As I mentioned in my last blog post, GSoC was a great learning experience and I’m willing to keep learning about the Linux graphics stack. Fortunately, when I started the Igalia CE, &lt;a href=&quot;https://melissawen.github.io/&quot;&gt;Melissa Wen&lt;/a&gt; pitched me a project to increase IGT test coverage on DRM/V3D kernel driver. I was pretty glad to hear about the project as it allowed me to learn more about how a GPU works.&lt;/p&gt;

&lt;h2 id=&quot;the-project&quot;&gt;The Project&lt;/h2&gt;

&lt;p&gt;Currently, V3D only has three basic IGT tests: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v3d_get_bo_offset&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v3d_get_param&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v3d_mmap&lt;/code&gt;. So, the basic goal of my CE project was to add more tests to the V3D driver.&lt;/p&gt;

&lt;p&gt;As the general DRM-core tests were in a good shape on the V3D driver, I started to think together with my mentors about more driver-specific tests for the driver.&lt;/p&gt;

&lt;p&gt;By checking the V3D UAPI, you can see that the V3D has eleven ioctls, so there is yet a lot to test for the V3D on IGT.&lt;/p&gt;

&lt;p&gt;First, there are Buffer Object (BO) related-ioctls: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v3d_create_bo&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v3d_wait_bo&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v3d_mmap_bo&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v3d_get_bo_offset&lt;/code&gt;. The Buffer Objects are shared-memory objects that are allocated by the GPU to store things like vertex data. Therefore, testing them is important to make sure that memory is being correctly allocated. Different from the VC4, the V3D has an MMU between the GPU and the bus, allowing it to not allocate objects contiguously. Therefore, the idea was to develop tests for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v3d_create_bo&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v3d_wait_bo&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next, there are Performance Monitor (perfmon) related-ioctls: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v3d_perfmon_create&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v3d_perfmon_destroy&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v3d_perfmon_get_values&lt;/code&gt;. Performance Monitors are basically registers that are used for monitoring the performance of the V3D engine. So, tests were designed to assure that the driver was creating perfmons properly and was resilient to incorrect requests, such as trying to get a value from a non-existent perfmon.&lt;/p&gt;

&lt;p&gt;And finally, the most interesting type of ioctls: the job submission ioctls. You can use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v3d_submit_cl&lt;/code&gt; ioctl to submit commands to the 3D engine, which is a tiled engine. When I think about tiled rendering, I always think about a &lt;a href=&quot;https://www.youtube.com/@RGMechEx&quot;&gt;Super Nintendo&lt;/a&gt;, but things can get a bit more complicated than a SNES as you can see &lt;a href=&quot;https://developer.samsung.com/galaxy-gamedev/resources/articles/gpu-framebuffer.html&quot;&gt;here&lt;/a&gt;. The 3D engine is composed of a bin and render pipelines, each has its command list. The binning step maps the tile to a piece of the frame and the rendering step renders the tile based on its mapping.&lt;/p&gt;

&lt;p&gt;By testing the v3d_submit_cl ioctl, it is possible to test syncing between jobs and also the &lt;a href=&quot;https://melissawen.github.io/blog/2022/05/10/multisync-p1&quot;&gt;V3D multisync ability&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Moreover, the V3D has also a TFU (texture formatting unit), and a CSD (compute shader dispatch), which has their ioctls: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v3d_submit_tfu&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v3d_submit_csd&lt;/code&gt;. The TFU makes format conversions and generated mipmaps and the CSD is responsible for dispatching a compute shader.&lt;/p&gt;

&lt;p&gt;So, the idea is to write tests for all those functionalities from V3D, increasing the testability of V3D on IGT. Although things are not yet fully-done, I’ve been enjoying and working exploring the V3D, IGT, and Mesa. After this experience with Mesa and also XDC, I became more and more interested in Mesa.&lt;/p&gt;

&lt;h2 id=&quot;a-noop-job&quot;&gt;A Noop Job…&lt;/h2&gt;

&lt;p&gt;In order to test the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v3d_submit_cl&lt;/code&gt; ioctl, it was needed to design a job to be submitted. So, Melissa suggested using Mesa’s noop job specification on IGT to perform the tests. The idea was quite simple: submit a noop job and create tests based on it. But, it was not that simple after all…&lt;/p&gt;

&lt;p&gt;First, I must say that I’m mostly a kernel developer, so I was not familiar with Mesa. So, maybe it was not that hard to figure out, but I took a while to understand Mesa’s packet and how to submit them.&lt;/p&gt;

&lt;p&gt;The main problem I faced on submitting a noop job on IGT was: I would copy many and many Mesa files to IGT. And I took a while fighting against this idea, looking for other ways to submit a job to V3D. But, as some experience developers pointed out, packeting is the best option for it.&lt;/p&gt;

&lt;p&gt;After some time, I was able to bring the Mesa structure to IGT with a minimal (although not that minimal) overhead. But, I’m still not able to run a successful noop job as the job’s fence is not being signaled by the end of the job.&lt;/p&gt;

&lt;h2 id=&quot;series-submitted&quot;&gt;Series Submitted&lt;/h2&gt;

&lt;p&gt;Although my noop job has not landed yet, so far, I was able to submit two series to IGT: &lt;a href=&quot;https://patchwork.freedesktop.org/series/110681/&quot;&gt;one for the V3D driver&lt;/a&gt; and &lt;a href=&quot;https://patchwork.freedesktop.org/series/110948/&quot;&gt;the other for the VC4 driver&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Apart from cleanups in the drivers, I added tests for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v3d_create_bo&lt;/code&gt; ioctl and the V3D’s and VC4’s perfmon ioctls. Moreover, as I was running the VC4 tests on the Raspberry Pi 4, I realized that most of the VC4 tests were failing on V3D, considering the VC4 doesn’t have rendering abilities on the Raspberry Pi 4. So, I also created checks to assure that the VC4 tests are not running on V3D.&lt;/p&gt;

&lt;p&gt;Those series are being reviewed yet, but I hope to get them merged soon.&lt;/p&gt;

&lt;h1 id=&quot;next-steps&quot;&gt;Next Steps&lt;/h1&gt;

&lt;hr /&gt;

&lt;p&gt;My biggest priority now is to run a noop job on IGT and for it, I’m currently running the CTS tests on the Raspberry Pi 4 in order to reproduce a noop job and understand why my current job is resulting in a hang. I added a couple of debug logs (aka &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;printf&lt;/code&gt;) on Mesa and now I can see the contents of the BOs and the parameters of the submission. So, I hope to get a fully-working noop job now.&lt;/p&gt;

&lt;p&gt;After I develop my fully working noop job, I will finish the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v3d_wait_bo&lt;/code&gt; tests, so those only make sense if I submit a job and wait for a BO after it and design the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v3d_submit_cl&lt;/code&gt; tests as well. For this last one, I hope to test the syncing functionalities of V3D especially.&lt;/p&gt;

&lt;p&gt;Moreover, I hope to write soon a piece about cross-compiling CTS for the Raspberry Pi 4, which was a fun digression on this CE project.&lt;/p&gt;
</description>
                <pubDate>Thu, 08 Dec 2022 00:00:00 +0000</pubDate>
                <link>https://mairacanal.github.io/november-update-exploring-v3d/</link>
                <guid isPermaLink="true">https://mairacanal.github.io/november-update-exploring-v3d/</guid>
            </item>
        
    </channel>
</rss>
