<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Oke Habeeb Adedayo</title>
    <description>The latest articles on DEV Community by Oke Habeeb Adedayo (@adedayoke).</description>
    <link>https://dev.to/adedayoke</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1209544%2F91811510-f3e4-40e7-a86f-97763fd4ac0b.png</url>
      <title>DEV Community: Oke Habeeb Adedayo</title>
      <link>https://dev.to/adedayoke</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/adedayoke"/>
    <language>en</language>
    <item>
      <title>Run QNX 8.0 on Windows with WSL2 and capture your first kernel trace</title>
      <dc:creator>Oke Habeeb Adedayo</dc:creator>
      <pubDate>Wed, 11 Nov 2026 04:36:30 +0000</pubDate>
      <link>https://dev.to/adedayoke/run-qnx-80-on-windows-with-wsl2-and-capture-your-first-kernel-trace-5ekg</link>
      <guid>https://dev.to/adedayoke/run-qnx-80-on-windows-with-wsl2-and-capture-your-first-kernel-trace-5ekg</guid>
      <description>&lt;p&gt;&lt;em&gt;Written for the QNX Global Hackathon. The original lives &lt;a href="https://github.com/Adedayoke/kevlint/blob/main/docs/tutorial-qnx-wsl.md" rel="noopener noreferrer"&gt;on GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;By the end of this tutorial you will have QNX 8.0 running in a virtual machine on your Windows laptop, and you will have recorded and read a real kernel trace: every thread switch, with priorities and timestamps.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;You need&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A Windows laptop. No QNX experience and no extra hardware.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Disk space&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;About 7 GB free in WSL. The installer lists SDP 8.0 at about 6.4 GB; it took 3.5 GB on disk in our install.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Downloads&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;For metered connections: the Ubuntu 24.04 WSL image is about 360 MB, the QNX Software Center installer about 100 MB, &lt;code&gt;qemu-system-x86&lt;/code&gt; about 49 MB, and SDP 8.0 several GB (6.4 GB installed, per the installer). Skip the 20 GB Quick Start package: step 4 builds the image locally instead.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Memory&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The virtual machine uses 1 GB. This setup runs on a laptop with 8 GB of RAM.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total time&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;About 90 minutes, most of it in steps 1 to 3. Step times are estimates.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Free: the QNX license is for personal, non-commercial use.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Here is what you are building. The numbers on the right are the steps that set up each layer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Windows laptop
└── WSL2: Ubuntu 24.04                     steps 2, 3
    ├── QNX SDP 8.0 in ~/qnx800            step 3 (qcc, mkqnximage, traceprinter)
    └── QEMU                               steps 4, 5
        └── QNX 8.0 guest                  step 6 (SSH on localhost:2222)
            └── tracelogger                step 7 (writes the kernel trace)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How this tutorial was checked
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Steps 4 to 7 were replayed on 2026-11-09&lt;/strong&gt; on freshly built images, with these commands. The only differences were the folder and the SSH port (2223 instead of 2222). Each step is marked &lt;strong&gt;Tested on a fresh image&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Steps 1 to 3 come from the original setup&lt;/strong&gt; and were not replayed, because they happen on qnx.com and in graphical installers. Each is marked &lt;strong&gt;Not replayed&lt;/strong&gt;. Screens and button names may differ from what you see.&lt;/li&gt;
&lt;li&gt;Anything else we could not confirm is marked &lt;strong&gt;Unverified&lt;/strong&gt; where it appears.&lt;/li&gt;
&lt;li&gt;This combination is not an officially documented one. QNX's guide says &lt;a href="https://www.qnx.com/developers/docs/qnxeverywhere/com.qnx.doc.target_images/topic/qsti_qemu/about.html" rel="noopener noreferrer"&gt;the QSTI for QEMU runs on Ubuntu 22.04 or 24.04&lt;/a&gt;, and that page does not mention WSL.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step 1: Get a free QNX license
&lt;/h2&gt;

&lt;p&gt;⏱ About 10 minutes · &lt;strong&gt;Not replayed&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In your Windows browser, go to &lt;a href="https://www.qnx.com/getqnx" rel="noopener noreferrer"&gt;qnx.com/getqnx&lt;/a&gt; and request the free non-commercial license (QNX Everywhere). You need a myQNX account.&lt;/li&gt;
&lt;li&gt;In myQNX, &lt;strong&gt;accept&lt;/strong&gt; the license and &lt;strong&gt;deploy&lt;/strong&gt; it to your account.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;You should see:&lt;/strong&gt; the license listed in myQNX as deployed. The installer in step 3 needs it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Troubleshooting&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The license doesn't show up in the installer in step 3.&lt;/strong&gt; Come back here and check that you both accepted and deployed it. Accepting alone is not the last step.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 2: Install WSL2 with Ubuntu 24.04
&lt;/h2&gt;

&lt;p&gt;⏱ About 15 minutes · &lt;strong&gt;Not replayed&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In Windows PowerShell:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;wsl&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="nc"&gt;Ubuntu&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;24.04&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use 24.04 specifically. QNX documents 22.04 and 24.04, and newer Ubuntu releases are untested here. Windows may ask you to reboot and to create a Linux username and password (&lt;strong&gt;Unverified&lt;/strong&gt;: this depends on your Windows setup).&lt;/p&gt;

&lt;p&gt;Open the Ubuntu terminal and bring it up to date:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sudo apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; sudo apt upgrade -y
&lt;span class="nb"&gt;cd&lt;/span&gt; ~
&lt;span class="nb"&gt;pwd&lt;/span&gt;
grep VERSION_ID /etc/os-release
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$DISPLAY&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;You should see:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/home/&amp;lt;your-linux-name&amp;gt;
VERSION_ID="24.04"
:0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;:0&lt;/code&gt; means WSLg is available, so Linux graphical apps can open on your Windows desktop.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Work in your Linux home folder for everything that follows, not under &lt;code&gt;/mnt/c&lt;/code&gt;.&lt;/strong&gt; &lt;code&gt;/mnt/c&lt;/code&gt; is your Windows drive, and nothing in this tutorial has been tested there.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Troubleshooting&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;VERSION_ID&lt;/code&gt; isn't 24.04.&lt;/strong&gt; You may have another distribution as the default. Run &lt;code&gt;wsl --list --verbose&lt;/code&gt; in PowerShell and open the Ubuntu-24.04 one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;$DISPLAY&lt;/code&gt; is empty.&lt;/strong&gt; Step 3's installer needs a display, so sort this out before going on. WSLg comes with current WSL versions; &lt;code&gt;wsl --update&lt;/code&gt; in PowerShell is the first thing to try (&lt;strong&gt;Unverified&lt;/strong&gt;: we did not hit this).&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 3: Install QNX SDP 8.0
&lt;/h2&gt;

&lt;p&gt;⏱ About 30 minutes, mostly download · &lt;strong&gt;Not replayed&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In your Windows browser, download the &lt;strong&gt;QNX Software Center&lt;/strong&gt; installer for &lt;strong&gt;Linux Hosts&lt;/strong&gt;. Choose Linux even though you're on Windows, because it will run inside WSL.&lt;/li&gt;
&lt;li&gt;Copy it into WSL and run it as your normal user, with no &lt;code&gt;sudo&lt;/code&gt;. Replace &lt;code&gt;&amp;lt;you&amp;gt;&lt;/code&gt; with your Windows user name. Our file was &lt;code&gt;qnx-setup-2.0.4-202501021438-linux.run&lt;/code&gt; (about 104 MB); yours may have a newer version.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   cp /mnt/c/Users/&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;you&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/Downloads/qnx-setup-*-linux.run ~/
   chmod +x ~/qnx-setup-*-linux.run
   ~/qnx-setup-*-linux.run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;The Software Center went into &lt;code&gt;~/qnx/qnxsoftwarecenter&lt;/code&gt; on our machine. Its window opens on the Windows desktop through WSLg. If it isn't already open, start it:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   ~/qnx/qnxsoftwarecenter/qnxsoftwarecenter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Sign in, then install &lt;strong&gt;QNX SDP 8.0&lt;/strong&gt; (ours was Build 141, shown with an Installed Size of about 6.4 GB) into the folder &lt;code&gt;~/qnx800&lt;/code&gt;. Type the full path, &lt;code&gt;/home/&amp;lt;your-linux-name&amp;gt;/qnx800&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Skip the Quick Start QEMU image package.&lt;/strong&gt; The installer listed it at &lt;code&gt;Installed Size: 20.0 GB&lt;/code&gt;. The image you build in step 4 is about 170 MB.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Check the install. &lt;strong&gt;You will run this &lt;code&gt;source&lt;/code&gt; line in every new terminal that uses the QNX tools:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;source&lt;/span&gt; ~/qnx800/qnxsdp-env.sh
which qcc mkqnximage traceprinter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;You should see&lt;/strong&gt; three paths:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/home/&amp;lt;your-linux-name&amp;gt;/qnx800/host/linux/x86_64/usr/bin/qcc
/home/&amp;lt;your-linux-name&amp;gt;/qnx800/host/common/bin/mkqnximage
/home/&amp;lt;your-linux-name&amp;gt;/qnx800/host/linux/x86_64/usr/bin/traceprinter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Troubleshooting&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Script is being run, should be sourced&lt;/code&gt;.&lt;/strong&gt; You ran &lt;code&gt;./qnxsdp-env.sh&lt;/code&gt;. Use &lt;code&gt;source&lt;/code&gt; as shown, so it can change your current shell.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;which&lt;/code&gt; prints nothing.&lt;/strong&gt; The &lt;code&gt;source&lt;/code&gt; line didn't run in this terminal, or SDP went into a different folder. Check with &lt;code&gt;ls ~/qnx800&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The installer window doesn't open.&lt;/strong&gt; Test WSLg by itself: &lt;code&gt;sudo apt install -y x11-apps&lt;/code&gt;, then &lt;code&gt;xeyes&lt;/code&gt;. If that doesn't open a window either, the problem is WSLg, not QNX.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 4: Build a QNX image
&lt;/h2&gt;

&lt;p&gt;⏱ About 5 minutes · &lt;strong&gt;Tested on a fresh image&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Install QEMU and create an SSH key. Skip the &lt;code&gt;ssh-keygen&lt;/code&gt; line if you already have &lt;code&gt;~/.ssh/id_ed25519&lt;/code&gt;: running it again would ask to overwrite your key.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sudo apt install -y qemu-system-x86 bridge-utils
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(&lt;code&gt;bridge-utils&lt;/code&gt; is only used by the network check in &lt;code&gt;mkqnximage --run&lt;/code&gt;, which step 5 replaces. It was installed on the machine we tested on.)&lt;/p&gt;

&lt;p&gt;Build the image in a new, empty folder. &lt;strong&gt;The folder must be &lt;code&gt;~/qnxvm&lt;/code&gt;&lt;/strong&gt;, because the launch script in step 5 expects it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;source&lt;/span&gt; ~/qnx800/qnxsdp-env.sh
mkdir ~/qnxvm
&lt;span class="nb"&gt;cd&lt;/span&gt; ~/qnxvm
mkqnximage --type=qemu --arch=x86_64 --ssh-ident=&lt;span class="nv"&gt;$HOME&lt;/span&gt;/.ssh/id_ed25519.pub --build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the &lt;code&gt;$HOME&lt;/code&gt;. The shell doesn't expand &lt;code&gt;~&lt;/code&gt; after an &lt;code&gt;=&lt;/code&gt; in the middle of an argument, so &lt;code&gt;--ssh-ident=~/.ssh/...&lt;/code&gt; would pass a literal &lt;code&gt;~&lt;/code&gt; to &lt;code&gt;mkqnximage&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The stock image can't accept SSH logins yet, because it doesn't include &lt;code&gt;sshd-auth&lt;/code&gt;, a helper program that this &lt;code&gt;sshd&lt;/code&gt; refuses to start without. Add it to the image, along with the links &lt;code&gt;sshd&lt;/code&gt; looks for in &lt;code&gt;/usr/libexec&lt;/code&gt;, then rebuild:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cat &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; local/snippets/ifs_env.custom &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="s1"&gt;'EOF'&lt;/span&gt;
procmgr_symlink /system/bin/sshd-session /usr/libexec/sshd-session
procmgr_symlink /system/bin/sshd-auth /usr/libexec/sshd-auth
EOF
cat &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; local/snippets/system_files.custom &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="s1"&gt;'EOF'&lt;/span&gt;
bin/sshd-auth=usr/libexec/sshd-auth
EOF
mkqnximage --build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your options are remembered in &lt;code&gt;local/options&lt;/code&gt;, so the second build doesn't need them again. Each build took about 7 seconds for us.&lt;/p&gt;

&lt;p&gt;We tested this both ways. Without these lines, &lt;code&gt;sshd&lt;/code&gt; stops immediately with &lt;code&gt;/usr/libexec/sshd-auth does not exist or is not executable&lt;/code&gt;, and with them everything in steps 6 and 7 works. QNX's 8.0.2 networking release notes describe the same snippet files for adding &lt;code&gt;sshd-session&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Check the result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ls output/ifs.bin output/disk-qemu.vmdk
grep sshd-auth output/build/system.build output/build/ifs.build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;You should see:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;output/disk-qemu.vmdk  output/ifs.bin
output/build/system.build:bin/sshd-auth=usr/libexec/sshd-auth
output/build/ifs.build:procmgr_symlink /system/bin/sshd-auth /usr/libexec/sshd-auth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Troubleshooting&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;mkqnximage: command not found&lt;/code&gt;.&lt;/strong&gt; Run the &lt;code&gt;source&lt;/code&gt; line from step 3 in this terminal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It refuses to build in a non-empty directory.&lt;/strong&gt; &lt;code&gt;mkqnximage&lt;/code&gt; won't create a new image in a folder that already has files. Use a new empty folder.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You used &lt;code&gt;~&lt;/code&gt; by mistake in &lt;code&gt;--ssh-ident&lt;/code&gt;.&lt;/strong&gt; Run the full command again with &lt;code&gt;$HOME&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The &lt;code&gt;grep&lt;/code&gt; prints nothing.&lt;/strong&gt; You appended the snippets but didn't rebuild, or you were in a different folder. Run &lt;code&gt;cd ~/qnxvm&lt;/code&gt;, then &lt;code&gt;mkqnximage --build&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A warning for later:&lt;/strong&gt; &lt;code&gt;--build&lt;/code&gt; rebuilds every partition, including &lt;code&gt;/data&lt;/code&gt;. Rebuilding after step 6 erases the files you create there, so you'd repeat step 6.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 5: Start QNX with networking that works under WSL
&lt;/h2&gt;

&lt;p&gt;⏱ About 5 minutes · &lt;strong&gt;Tested on a fresh image&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The obvious command is &lt;code&gt;mkqnximage --run&lt;/code&gt;, but it uses bridge networking. Under WSL the guest only got a link-local address: &lt;code&gt;ifconfig&lt;/code&gt; showed &lt;code&gt;vtnet0&lt;/code&gt; at &lt;code&gt;169.254.237.236&lt;/code&gt;, which you can't reach for SSH.&lt;/p&gt;

&lt;p&gt;The fix is a small launch script. It starts QEMU the way &lt;code&gt;mkqnximage --run&lt;/code&gt; does on a machine without KVM, with one change: QEMU's user-mode networking, which forwards port 2222 on Linux to the guest's SSH port.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cat &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ~/qnxvm/run.sh &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="s1"&gt;'EOF'&lt;/span&gt;
&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; ~/qnxvm
qemu-system-x86_64 -smp 2 --cpu max -m 1G \
  -drive &lt;span class="nv"&gt;file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;output/disk-qemu.vmdk,if=ide,id=drv0 \
  -netdev user,id=net0,hostfwd=tcp::2222-:22 \
  -device virtio-net-pci,netdev=net0,mac=52:54:00:ff:98:86 \
  -pidfile output/qemu.pid -nographic -kernel output/ifs.bin -serial mon:stdio \
  -object rng-random,filename=/dev/urandom,id=rng0 -device virtio-rng-pci,rng=rng0
EOF
chmod +x ~/qnxvm/run.sh
~/qnxvm/run.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two things about this script:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--cpu max&lt;/code&gt; with no KVM means QEMU emulates the CPU in software. It's enough for this tutorial, but &lt;strong&gt;don't treat timings as real-time measurements&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The MAC address is a fixed value. It worked on images whose generated MAC was different, so you don't need to change it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This terminal is now the &lt;strong&gt;QNX console&lt;/strong&gt;, a root shell with no login. Boot took under 20 seconds for us.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You should see&lt;/strong&gt; boot messages ending with a &lt;code&gt;#&lt;/code&gt; prompt, including these two lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---&amp;gt; Starting sshd
Memory fault (core dumped)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;That memory fault is expected.&lt;/strong&gt; The stock &lt;code&gt;sshd&lt;/code&gt; crashes at every boot, and step 6 deals with it.&lt;/p&gt;

&lt;p&gt;At the &lt;code&gt;#&lt;/code&gt; prompt, type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ifconfig vtnet0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;You should see&lt;/strong&gt; a line containing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;inet 10.0.2.15 netmask 0xffffff00 broadcast 10.0.2.255
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Leave this terminal open, and open a second Ubuntu terminal for the next steps. To shut the virtual machine down later, press &lt;strong&gt;Ctrl-A, then X&lt;/strong&gt; in the console.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Troubleshooting&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Could not set up host forwarding rule 'tcp::2222-:22'&lt;/code&gt;.&lt;/strong&gt; Something already holds port 2222, usually another copy of QEMU. Find it with &lt;code&gt;pgrep -af qemu-system&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;vtnet0&lt;/code&gt; shows &lt;code&gt;169.254.x.x&lt;/code&gt;.&lt;/strong&gt; You started the image with &lt;code&gt;mkqnximage --run&lt;/code&gt;. Stop it and use &lt;code&gt;~/qnxvm/run.sh&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;vtnet0&lt;/code&gt; has no &lt;code&gt;inet&lt;/code&gt; line yet.&lt;/strong&gt; Wait a few seconds and run &lt;code&gt;ifconfig vtnet0&lt;/code&gt; again.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;qemu-system-x86_64: command not found&lt;/code&gt;.&lt;/strong&gt; The &lt;code&gt;apt install&lt;/code&gt; in step 4 didn't complete.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 6: Get SSH working
&lt;/h2&gt;

&lt;p&gt;⏱ About 10 minutes · &lt;strong&gt;Tested on a fresh image&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;From your &lt;strong&gt;second&lt;/strong&gt; terminal, see the problem for yourself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh -p 2222 root@localhost
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;You should see:&lt;/strong&gt; &lt;code&gt;Connection reset by 127.0.0.1 port 2222&lt;/code&gt;. QEMU accepts the connection, but no working &lt;code&gt;sshd&lt;/code&gt; is behind it. The stock configuration, &lt;code&gt;/system/etc/ssh/sshd_config&lt;/code&gt;, has &lt;code&gt;UsePAM yes&lt;/code&gt;, and turning PAM off is what stops the crash. You will run your own &lt;code&gt;sshd&lt;/code&gt; with PAM off.&lt;/p&gt;

&lt;p&gt;Paste this whole block into the &lt;strong&gt;QNX console&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cat &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /data/home/root/sshd_nopam.conf &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="s1"&gt;'EOF'&lt;/span&gt;
HostKey /data/var/ssh/ssh_host_ed25519_key
UsePAM no
PasswordAuthentication no
PidFile none
AuthorizedKeysFile .ssh/authorized_keys
Subsystem sftp /system/bin/sftp-server
SshdSessionPath /system/bin/sshd-session
PermitUserEnvironment yes
EOF
cat &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /data/home/root/.ssh/environment &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="s1"&gt;'EOF'&lt;/span&gt;
&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/proc/boot:/system/bin
EOF
chmod 600 /data/home/root/.ssh/environment
cat &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /data/home/root/start_ssh.sh &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="s1"&gt;'EOF'&lt;/span&gt;
/system/bin/sshd -D -e -f /data/home/root/sshd_nopam.conf &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /tmp/sshd.log 2&lt;span class="o"&gt;&amp;gt;&amp;amp;&lt;/span&gt;1 &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;
EOF
sh /data/home/root/start_ssh.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What the less obvious pieces do:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Piece&lt;/th&gt;
&lt;th&gt;Why it's there&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;UsePAM no&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Avoids the PAM crash.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;PasswordAuthentication no&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Log in only with the key you built into the image in step 4.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Subsystem sftp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The &lt;code&gt;scp&lt;/code&gt; on Ubuntu 24.04 needs it to copy files.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SshdSessionPath&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Where this image keeps &lt;code&gt;sshd-session&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;PermitUserEnvironment yes&lt;/code&gt; and &lt;code&gt;.ssh/environment&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Remote commands get &lt;code&gt;PATH=/proc/boot:/system/bin&lt;/code&gt;, so they can find &lt;code&gt;tracelogger&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sshd -D -e&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Keeps &lt;code&gt;sshd&lt;/code&gt; in the foreground and sends its log to stderr, which goes to &lt;code&gt;/tmp/sshd.log&lt;/code&gt;. The &lt;code&gt;&amp;amp;&lt;/code&gt; runs it in the background.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;From your &lt;strong&gt;second&lt;/strong&gt; terminal, wait a few seconds and test it. Answer &lt;code&gt;yes&lt;/code&gt; to the first-connection host key question.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh -p 2222 root@localhost uname -a
ssh -p 2222 root@localhost &lt;span class="s1"&gt;'echo $PATH; which tracelogger'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;You should see:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;QNX noname 8.0.0 2026/06/05-16:26:03EDT x86pc x86_64
/proc/boot:/system/bin
/system/bin/tracelogger
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;sshd&lt;/code&gt; you just started doesn't survive a reboot. After every boot, run &lt;code&gt;sh /data/home/root/start_ssh.sh&lt;/code&gt; on the console.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Troubleshooting&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The paste comes out garbled, with &lt;code&gt;^M&lt;/code&gt; characters or lines run together.&lt;/strong&gt; This happened on a first paste and worked on the second. Press Ctrl-C, then paste again one &lt;code&gt;cat&lt;/code&gt; block at a time, from the &lt;code&gt;cat&lt;/code&gt; line to its &lt;code&gt;EOF&lt;/code&gt;, followed by the &lt;code&gt;chmod&lt;/code&gt; and &lt;code&gt;sh&lt;/code&gt; lines. Pasting a block again overwrites the file it writes. Check the result with &lt;code&gt;cat /data/home/root/sshd_nopam.conf&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Connection reset by 127.0.0.1 port 2222&lt;/code&gt;.&lt;/strong&gt; Your &lt;code&gt;sshd&lt;/code&gt; isn't running. On the console, run &lt;code&gt;cat /tmp/sshd.log&lt;/code&gt; to see why, then &lt;code&gt;sh /data/home/root/start_ssh.sh&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The log says &lt;code&gt;/usr/libexec/sshd-auth does not exist or is not executable&lt;/code&gt;.&lt;/strong&gt; The snippets from step 4 aren't in your image. Add them, rebuild, boot, and repeat this step.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Connection refused&lt;/code&gt;.&lt;/strong&gt; QEMU itself isn't running. Start it with &lt;code&gt;~/qnxvm/run.sh&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;REMOTE HOST IDENTIFICATION HAS CHANGED&lt;/code&gt;.&lt;/strong&gt; You probably built a new image in a new folder, which creates new host keys. Run &lt;code&gt;ssh-keygen -R '[localhost]:2222'&lt;/code&gt; and connect again.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;tracelogger: not found&lt;/code&gt; over SSH.&lt;/strong&gt; The &lt;code&gt;.ssh/environment&lt;/code&gt; file is missing or &lt;code&gt;PermitUserEnvironment yes&lt;/code&gt; didn't make it into the config. Look at both on the console.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 7: Capture and read your first kernel trace
&lt;/h2&gt;

&lt;p&gt;⏱ About 10 minutes · &lt;strong&gt;Tested on a fresh image&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The kernel in this image is the instrumented one, so it can log its own events. &lt;code&gt;tracelogger&lt;/code&gt; saves them to a file. From your &lt;strong&gt;second&lt;/strong&gt; terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh -p 2222 root@localhost &lt;span class="s1"&gt;'tracelogger -w -s 3 -f /tmp/test.kev'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This runs for about 3 seconds (3.4 to 4.8 s in our runs) and &lt;strong&gt;prints nothing when it succeeds&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-s 3&lt;/code&gt; records for 3 seconds.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-f&lt;/code&gt; names the output file.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-w&lt;/code&gt; selects wide mode. &lt;strong&gt;Always use it: only wide mode includes each thread's priority and policy.&lt;/strong&gt; Here's the same kind of event from two real traces:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  without -w   t:0x486e342fc13 CPU:00 THREAD :THRUNNING  pid:1 tid:3
  with -w      t:0x4df2976264c CPU:00 THREAD :THRUNNING  pid:1 tid:3 priority:255 policy:8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy the file to Linux and decode it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;source&lt;/span&gt; ~/qnx800/qnxsdp-env.sh
mkdir -p ~/traces
&lt;span class="nb"&gt;cd&lt;/span&gt; ~/traces
scp -P 2222 root@localhost:/tmp/test.kev .
traceprinter -f test.kev &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; test.txt
ls -la test.kev
wc -l test.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;You should see:&lt;/strong&gt; a &lt;code&gt;.kev&lt;/code&gt; file of a few hundred KB (ours was 333,741 bytes on an idle system) and about 20,000 lines of text. Your exact numbers will differ.&lt;/p&gt;

&lt;h3&gt;
  
  
  Read the header
&lt;/h3&gt;

&lt;p&gt;The top of &lt;code&gt;test.txt&lt;/code&gt; describes the capture. Two lines matter most:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  TRACE_CYCLES_PER_SEC:: 2648529944
TRACE_TRACELOGGER_ARGS:: tracelogger -w -s 3 -f /tmp/test.kev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Timestamps are in CPU cycles, and the rate changed between boots for us, so read yours from your own file. Check for &lt;code&gt;-w&lt;/code&gt; in the second line.&lt;/p&gt;

&lt;h3&gt;
  
  
  Read an event
&lt;/h3&gt;

&lt;p&gt;Here are three real lines for one thread, with the lines between them removed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;t:0x128a4c0787 CPU:01 THREAD          :THSEM              pid:725013 tid:4 priority:10 policy:2
t:0x128a920384 CPU:00 THREAD          :THREADY            pid:725013 tid:4 priority:10 policy:2
t:0x128acf8778 CPU:01 THREAD          :THRUNNING          pid:725013 tid:4 priority:10 policy:2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;t:0x...&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The timestamp, in cycles (hexadecimal).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CPU:01&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The CPU that logged the event.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;THREAD :THSEM&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The event class, then the event: this thread's new state.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;pid&lt;/code&gt;, &lt;code&gt;tid&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Which process and thread.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;priority:10&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The thread's priority at that moment. Only wide mode has this.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;policy:2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The scheduling policy. In &lt;code&gt;sched.h&lt;/code&gt;, 1 is &lt;code&gt;SCHED_FIFO&lt;/code&gt; and 2 is &lt;code&gt;SCHED_RR&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The state tells you what the thread is doing:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;State&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;THRUNNING&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Running on a CPU right now.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;THREADY&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Able to run, but waiting for a CPU.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;THSEM&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Blocked on a semaphore.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;THRECEIVE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Waiting to receive a message: normal for an idle server.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;So the three lines tell a short story. The thread blocked on a semaphore, became ready, then got a CPU.&lt;/p&gt;

&lt;h3&gt;
  
  
  Turn timestamps into time
&lt;/h3&gt;

&lt;p&gt;Subtract two timestamps and divide by &lt;code&gt;TRACE_CYCLES_PER_SEC&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 -c &lt;span class="s2"&gt;"print((0x128a920384 - 0x128a4c0787) / 2648529944 * 1000, 'ms')"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;You should see&lt;/strong&gt; about &lt;code&gt;1.73 ms&lt;/code&gt;: how long the thread above stayed blocked. It then waited about 1.52 ms in &lt;code&gt;THREADY&lt;/code&gt; for a CPU. Remember that QEMU emulates the CPU, so use these numbers for practice, not as measurements.&lt;/p&gt;

&lt;h3&gt;
  
  
  Explore
&lt;/h3&gt;

&lt;p&gt;Count the states in your trace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;grep -oE &lt;span class="s1"&gt;'THREAD +:TH[A-Z_]+'&lt;/span&gt; test.txt &lt;span class="o"&gt;|&lt;/span&gt; sed &lt;span class="s1"&gt;'s/.*://'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; sort &lt;span class="o"&gt;|&lt;/span&gt; uniq -c &lt;span class="o"&gt;|&lt;/span&gt; sort -rn &lt;span class="o"&gt;|&lt;/span&gt; head -4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;You should see&lt;/strong&gt; something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   1605 THRUNNING
   1448 THREADY
    523 THINTR
    308 THRECEIVE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Find out who a &lt;code&gt;pid&lt;/code&gt; is, using a &lt;code&gt;pid&lt;/code&gt; from your own trace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;grep -A2 -E &lt;span class="s1"&gt;'^ +pid:725013$'&lt;/span&gt; test.txt &lt;span class="o"&gt;|&lt;/span&gt; grep name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Names come from multi-line &lt;code&gt;PROCCREATE_NAME&lt;/code&gt; and &lt;code&gt;PROCTHREAD_NAME&lt;/code&gt; events. That &lt;code&gt;pid&lt;/code&gt; was &lt;code&gt;system/bin/tracelogger&lt;/code&gt;: the trace recorded the tool that took it.&lt;/p&gt;

&lt;p&gt;Don't be surprised by the start of the file. Tracing begins with a dump of the current state of every thread, so you'll see many &lt;code&gt;THCREATE&lt;/code&gt; lines and states that repeat ones logged moments earlier.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Troubleshooting&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No &lt;code&gt;priority:&lt;/code&gt; on &lt;code&gt;THREAD&lt;/code&gt; lines.&lt;/strong&gt; You left out &lt;code&gt;-w&lt;/code&gt;. Capture again.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;traceprinter: command not found&lt;/code&gt;.&lt;/strong&gt; Run the &lt;code&gt;source&lt;/code&gt; line in this terminal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The trace is much shorter than 3 seconds.&lt;/strong&gt; &lt;code&gt;/tmp&lt;/code&gt; may be full: &lt;code&gt;tracelogger&lt;/code&gt; can exit with status 0 and print nothing while the file stops where the disk did. Check with &lt;code&gt;ssh -p 2222 root@localhost df -h /tmp&lt;/code&gt;. &lt;code&gt;/tmp&lt;/code&gt; lives on the small &lt;code&gt;/data&lt;/code&gt; partition (about 50 MB free on a fresh image), and a busy system can write about 2 MB/s. Delete old traces with &lt;code&gt;rm /tmp/*.kev&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;scp: Connection closed&lt;/code&gt;.&lt;/strong&gt; &lt;code&gt;sshd&lt;/code&gt; isn't running, or the &lt;code&gt;Subsystem sftp&lt;/code&gt; line is missing. See step 6.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 8 (optional): Check the trace with kevlint
&lt;/h2&gt;

&lt;p&gt;⏱ About 5 minutes · &lt;strong&gt;Tested on a fresh trace&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Adedayoke/kevlint" rel="noopener noreferrer"&gt;kevlint&lt;/a&gt; checks traces against timing rules, such as "no priority inversion", and needs only Python 3. Keep using the same Ubuntu terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~
git clone https://github.com/Adedayoke/kevlint.git
&lt;span class="nb"&gt;cd&lt;/span&gt; kevlint
&lt;span class="nv"&gt;PYTHONPATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;host python3 -m kevlint check ~/traces/test.txt --html ~/traces/first.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;You should see&lt;/strong&gt; something like this, with different counts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rule: priority-inversion

0 violation(s)
blocks: 61 total, 3 evaluated, 58 not evaluated
  not evaluated: 1 (block still open when the trace ended)
  not evaluated: 1 (blocked in THMUON_MUTEX, which this rule does not check)
  not evaluated: 56 (no matching wait call in the trace)
PASS: 0 violation(s) in 3 evaluated block(s); 58 block(s) not evaluated
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Read the second half of that PASS line.&lt;/strong&gt; On an idle system kevlint could only evaluate 3 blocks of 61, so this PASS says very little. To see what a real finding looks like, run it on the trace that ships with the repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;PYTHONPATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;host python3 -m kevlint check fixtures/demo_inversion.txt --html ~/traces/inversion.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;You should see&lt;/strong&gt; a last result line starting with &lt;code&gt;FAIL: 10 violation(s)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Open the HTML report in your Windows browser in either of two ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;From Ubuntu, run &lt;code&gt;explorer.exe ~/traces/inversion.html&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Paste &lt;code&gt;\\wsl.localhost\Ubuntu-24.04\home\&amp;lt;your-linux-name&amp;gt;\traces\inversion.html&lt;/code&gt; into the browser's address bar.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Troubleshooting&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;No module named kevlint&lt;/code&gt;.&lt;/strong&gt; Run the command from inside the &lt;code&gt;kevlint&lt;/code&gt; folder, with &lt;code&gt;PYTHONPATH=host&lt;/code&gt; at the front.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It exits with status 1.&lt;/strong&gt; That means violations were found, not that kevlint failed. Status 2 means it couldn't use the trace.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  You did it
&lt;/h2&gt;

&lt;p&gt;You now have QNX 8.0 on your laptop and a kernel trace you can read.&lt;/p&gt;

&lt;h3&gt;
  
  
  What survives what
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Reboot of the VM&lt;/th&gt;
&lt;th&gt;Rebuilding with &lt;code&gt;mkqnximage --build&lt;/code&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;/data&lt;/code&gt;, including your SSH files from step 6&lt;/td&gt;
&lt;td&gt;✅ Kept&lt;/td&gt;
&lt;td&gt;❌ Erased&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;/tmp&lt;/code&gt; (a link to &lt;code&gt;/data/var/tmp&lt;/code&gt;), including traces&lt;/td&gt;
&lt;td&gt;✅ Kept in our test&lt;/td&gt;
&lt;td&gt;❌ Erased&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The running &lt;code&gt;sshd&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;❌ Start it again&lt;/td&gt;
&lt;td&gt;❌ Start it again, after repeating step 6&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Because &lt;code&gt;/tmp&lt;/code&gt; is on &lt;code&gt;/data&lt;/code&gt;, old traces keep using its limited space until you delete them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Coming back later
&lt;/h3&gt;

&lt;p&gt;In one terminal, boot the image, and at the &lt;code&gt;#&lt;/code&gt; prompt start SSH:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~/qnxvm/run.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sh /data/home/root/start_ssh.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In a second terminal, you're ready to go:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;source&lt;/span&gt; ~/qnx800/qnxsdp-env.sh
ssh -p 2222 root@localhost
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To stop the virtual machine, press &lt;strong&gt;Ctrl-A, then X&lt;/strong&gt; on the console.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where to go next
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Compile a program for the target with &lt;code&gt;qcc -Vgcc_ntox86_64 -o out file.c&lt;/code&gt;, copy it over with &lt;code&gt;scp -P 2222&lt;/code&gt;, and trace it.&lt;/li&gt;
&lt;li&gt;Read &lt;a href="https://github.com/Adedayoke/kevlint/blob/main/README.md" rel="noopener noreferrer"&gt;kevlint's README&lt;/a&gt; to see how a trace can fail a CI build.&lt;/li&gt;
&lt;li&gt;See &lt;a href="https://github.com/Adedayoke/kevlint/blob/main/docs/qnx-trace-quirks.md" rel="noopener noreferrer"&gt;QNX trace quirks&lt;/a&gt; for behaviour we found while working with real traces.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>qnx</category>
      <category>wsl</category>
      <category>embedded</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
