<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Kernel on A journey into a wild pointer</title>
    <link>https://carette.xyz/tags/kernel/</link>
    <description>Recent content in Kernel on A journey into a wild pointer</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <lastBuildDate>Mon, 28 Sep 2026 10:11:00 +0200</lastBuildDate><atom:link href="https://carette.xyz/tags/kernel/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>A minimal kernel in Swift, running in QEMU</title>
      <link>https://carette.xyz/posts/minimal_swift_kernel_on_qemu/</link>
      <pubDate>Mon, 28 Sep 2026 10:11:00 +0200</pubDate>
      <guid>https://carette.xyz/posts/minimal_swift_kernel_on_qemu/</guid>
      <description>&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Update (28th of September 2026)&lt;/strong&gt;&lt;br&gt;
Max Desiatov &lt;a href=&#34;https://mastodon.social/@maxd/117348871405186390&#34;&gt;told me&lt;/a&gt; that &lt;a href=&#34;https://www.swift.org/blog/swift-6.3-released/#language-and-standard-library&#34;&gt;the &lt;code&gt;@c&lt;/code&gt; swift attribute&lt;/a&gt; should work, instead of declaring the functions using &lt;code&gt;@_cdecl&lt;/code&gt;. The &lt;code&gt;@c&lt;/code&gt; attribute marks a global function as a C function implemented in Swift, which formalizes the &lt;code&gt;@_cdecl&lt;/code&gt; attribute. A link to the proposal is available &lt;a href=&#34;https://github.com/swiftlang/swift-evolution/blob/main/proposals/0495-cdecl.md&#34;&gt;here&lt;/a&gt;.
I did update the blog post and the code accordingly to that comment. Thanks Max!&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;I started a small experiment: writing a very basic kernel in Swift, and running on &lt;a href=&#34;https://www.qemu.org&#34;&gt;QEMU&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The goal is obviously not to replace Linux or any other popular kernel, but just to have fun and understand what is required to make a program run without an operating system underneath it.&lt;br&gt;
Actually I made a similar experiment years before with &lt;a href=&#34;https://carette.xyz/posts/im_writing_my_own_os/&#34;&gt;arOS&lt;/a&gt; 10 years ago.&lt;/p&gt;
&lt;p&gt;For the moment, the kernel does only one thing: it prints a message through QEMU and then waits forever, which is enough for a first deep dive.&lt;/p&gt;
&lt;h2 class=&#34;heading&#34; id=&#34;swift-embedded&#34;&gt;
  Swift Embedded
  &lt;a class=&#34;anchor&#34; href=&#34;#swift-embedded&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;The project uses &lt;a href=&#34;https://docs.swift.org/latest/documentation/embeddedswift/&#34;&gt;Embedded Swift&lt;/a&gt;, which is a subset of Swift designed for environments where there is no operating system and no standard library available (in the usual sense).&lt;/p&gt;
&lt;p&gt;My first &lt;code&gt;Package.swift&lt;/code&gt; was very small:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// swift-tools-version: 6.4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic;text-decoration:underline&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;PackageDescription&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic;text-decoration:underline&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;package&lt;/span&gt; = Package(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name: &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;swift-kernel&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    platforms: [.macOS(.v14)],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    targets: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .executableTarget(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name: &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;swift_kernel&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            swiftSettings: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .enableExperimentalFeature(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Embedded&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .strictMemorySafety(),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .treatAllWarnings(&lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;as&lt;/span&gt;: .error),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And the first Swift file was almost insulting in its simplicity:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// Sources/swift_kernel/test.swift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Hello... world?&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I tried to run it:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt; swift run
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;unknown&amp;gt;:0: error: unable to load standard library &lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;for&lt;/span&gt; target &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;arm64-apple-macosx27.0.0&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Oops.
It seems like my current Swift compiler does not yet ship with the Embedded Swift standard library.&lt;/p&gt;
&lt;p&gt;As I missed in &lt;a href=&#34;https://docs.swift.org/latest/documentation/embeddedswift/installembeddedswift&#34;&gt;the documentation&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Since Embedded Swift is still experimental and not yet supported in public Swift releases, you’ll need to use a development toolchain.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So, let’s install the development toolchain and test again:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt; swiftly install main-snapshot &amp;amp;&amp;amp; swiftly use main-snapshot
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt; swift run
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[...]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Hello... world?
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Success!&lt;br&gt;
At this point I had confirmed that Embedded Swift could compile and run a small program.&lt;/p&gt;
&lt;p&gt;The next step was to compile for a machine with no operating system at all.&lt;/p&gt;
&lt;h2 class=&#34;heading&#34; id=&#34;qemu-setup&#34;&gt;
  QEMU setup
  &lt;a class=&#34;anchor&#34; href=&#34;#qemu-setup&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;For this project I will test on a machine emulator called &lt;a href=&#34;https://www.qemu.org/&#34;&gt;QEMU&lt;/a&gt;, which is one of the most famous machine emulators for hackers.&lt;/p&gt;
&lt;p&gt;I am using QEMU’s &lt;code&gt;virt&lt;/code&gt; machine on an Apple Silicon machine. The target is therefore &lt;code&gt;aarch64-none-none-elf&lt;/code&gt;.&lt;br&gt;
This target, designed &lt;a href=&#34;https://wiki.osdev.org/Target_Triplet&#34;&gt;as a triple&lt;/a&gt;, describes a 64-bit ARM machine with no operating system and no environment provided by a C runtime.&lt;/p&gt;
&lt;p&gt;When QEMU starts, the CPU is in a raw state.&lt;br&gt;
Before it can safely execute Swift code, I need to &lt;strong&gt;configure a stack&lt;/strong&gt; and &lt;strong&gt;decide where the program starts&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;I will need a minimal assembly file that:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;defines &lt;a href=&#34;http://dbp-consulting.com/tutorials/debugging/linuxProgramStartup.html&#34;&gt;the &lt;code&gt;_start&lt;/code&gt; symbol&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;sets up a stack for the first core,&lt;/li&gt;
&lt;li&gt;jumps to our Swift entry function, &lt;code&gt;kernel_main&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;and waits forever to keep the main running.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 class=&#34;heading&#34; id=&#34;compiler-setup&#34;&gt;
  Compiler setup
  &lt;a class=&#34;anchor&#34; href=&#34;#compiler-setup&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;I have to tell the compiler that this is not a normal executable: the compiler must avoid linking the usual standard libraries, and the linker must use our linker script instead of a platform-specific one.&lt;/p&gt;
&lt;p&gt;The project uses the following &lt;code&gt;toolset.json&lt;/code&gt;, which will be passed to our Swift Package Manager (SPM):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;#34;schemaVersion&amp;#34;: &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;1.0&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;#34;swiftCompiler&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;#34;extraCLIOptions&amp;#34;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;-enable-experimental-feature&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Embedded&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;-enable-experimental-feature&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Volatile&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;-Xfrontend&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;-no-allocations&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;-Xfrontend&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;-function-sections&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;-Xfrontend&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;-disable-stack-protector&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;-Xlinker-driver&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;-nostdlib&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;-Xlinker-driver&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;-fuse-ld=lld&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;#34;linker&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;#34;extraCLIOptions&amp;#34;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;-nostdlib&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;-static&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;--gc-sections&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;--orphan-handling=error&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;-T&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;linker.ld&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;-Map&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;.build/kernel.map&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, let’s build the project with the new target, the toolset, and Swift’s native build system:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt; swift build --triple aarch64-none-none-elf --toolset toolset.json --build-system native
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Unfortunately, the first linker attempt fails:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ld.lld: error: section type mismatch for .strtab
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; &amp;lt;internal&amp;gt;:(.strtab): SHT_STRTAB
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; output section .nonalloc: SHT_SYMTAB
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ld.lld: error: section type mismatch for .shstrtab
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; &amp;lt;internal&amp;gt;:(.shstrtab): SHT_STRTAB
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; output section .nonalloc: SHT_PROGBITS
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ld.lld: error: undefined symbol: putchar
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ld.lld: error: undefined symbol: memmove
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Hmm. What is going on here?&lt;/p&gt;
&lt;p&gt;Because I am compiling for a bare-metal target (reminder: &lt;code&gt;none-none-elf&lt;/code&gt;), there is no underlying operating system and no C standard library. Therefore there is no &lt;code&gt;putchar&lt;/code&gt;, and there is no &lt;code&gt;memmove&lt;/code&gt; either&amp;hellip;&lt;/p&gt;
&lt;p&gt;The section errors have a different origin.&lt;br&gt;
With orphan handling enabled, the linker does not want to guess where ELF metadata should go. Therefore, the linker script must explicitly place the sections that I am keeping.&lt;/p&gt;
&lt;h2 class=&#34;heading&#34; id=&#34;bridging-swift-to-assembly&#34;&gt;
  Bridging Swift to assembly
  &lt;a class=&#34;anchor&#34; href=&#34;#bridging-swift-to-assembly&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;I can&amp;rsquo;t use a normal Swift file with a &lt;code&gt;main&lt;/code&gt; function. Instead, I expose a designated kernel entry function with &lt;code&gt;@c&lt;/code&gt;, so that the assembly file can call it by its C-compatible name.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@c
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic;text-decoration:underline&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;kernel_main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Hello, Embedded Swift 😊&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;while&lt;/span&gt; &lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;true&lt;/span&gt; {} &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// Keep the program running&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The assembly entry point lives in &lt;code&gt;Sources/boot/boot.S&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.section &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.text.boot&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.global &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_start&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;_start:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;/* Read the CPU ID. We only want Core 0 to run our Swift code. */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;mrs&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x1&lt;/span&gt;, &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;mpidr_el1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;and&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x1&lt;/span&gt;, &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x1&lt;/span&gt;, &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;#3
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cbz&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x1&lt;/span&gt;, 2&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;f&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;/* Park secondary cores in an infinite wait loop. */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;&#34;&gt;1:&lt;/span&gt;  &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;wfe&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b&lt;/span&gt; 1&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;/* Set up the stack for Core 0. */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;&#34;&gt;2:&lt;/span&gt;  &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ldr&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x0&lt;/span&gt;, &lt;span style=&#34;&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;__stack_top&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;mov&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;sp&lt;/span&gt;, &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;/* Jump to our Swift entry point. */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;bl&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;kernel_main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;/* Halt if we ever return. */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b&lt;/span&gt; 1&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;QEMU can start multiple virtual cores but, for now, only the first one should execute our kernel.&lt;br&gt;
The other cores wait (using &lt;code&gt;wfe&lt;/code&gt;), waiting for an event that it will not send yet.&lt;/p&gt;
&lt;h2 class=&#34;heading&#34; id=&#34;providing-the-missing-functions&#34;&gt;
  Providing the missing functions
  &lt;a class=&#34;anchor&#34; href=&#34;#providing-the-missing-functions&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;print&lt;/code&gt; implementation used by Embedded Swift needs a way to write at least one character.&lt;br&gt;
On QEMU’s &lt;code&gt;virt&lt;/code&gt; machine, the &lt;a href=&#34;https://krinkinmu.github.io/2020/11/29/PL011.html&#34;&gt;ARMs PL011 UART&lt;/a&gt; is mapped at &lt;code&gt;0x09000000&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So &lt;code&gt;putchar&lt;/code&gt; can write directly to that memory-mapped register:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// QEMU&amp;#39;s PL011 UART register&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic;text-decoration:underline&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;QEMU_UART_REGISTER&lt;/span&gt;: &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;UInt&lt;/span&gt; = 0x0900_0000
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@c
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@unsafe &lt;span style=&#34;font-weight:bold;font-style:italic;text-decoration:underline&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;putchar&lt;/span&gt;(&lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;_&lt;/span&gt; c: &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;CInt&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;CInt&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;font-style:italic;text-decoration:underline&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;uart&lt;/span&gt; = unsafe &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;UnsafeMutablePointer&lt;/span&gt;&amp;lt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;UInt8&lt;/span&gt;&amp;gt;(bitPattern: QEMU_UART_REGISTER)!
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    unsafe uart.pointee = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;UInt8&lt;/span&gt;(c)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;return&lt;/span&gt; c
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;This is not a screen driver&lt;/strong&gt; but a serial output driver.&lt;br&gt;
QEMU will then display the bytes received &lt;strong&gt;by the emulated UART&lt;/strong&gt; in the terminal (because I will execute it with the &lt;code&gt;-nographic&lt;/code&gt; option).&lt;/p&gt;
&lt;p&gt;The other missing function is &lt;code&gt;memmove&lt;/code&gt;.&lt;br&gt;
Swift’s low-level code needs basic memory operations, even when I am not using a normal standard library.
For this first experiment, I provide a small implementation that copies forwards or backwards, depending on whether the source and destination overlap:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@c
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@unsafe &lt;span style=&#34;font-weight:bold;font-style:italic;text-decoration:underline&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;memmove&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;_&lt;/span&gt; dest: UnsafeMutableRawPointer,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;_&lt;/span&gt; src: UnsafeRawPointer,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;_&lt;/span&gt; n: &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;Int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;) -&amp;gt; UnsafeMutableRawPointer {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;font-style:italic;text-decoration:underline&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;d&lt;/span&gt; = unsafe dest.assumingMemoryBound(to: &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;UInt8&lt;/span&gt;.&lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;font-style:italic;text-decoration:underline&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;s&lt;/span&gt; = unsafe src.assumingMemoryBound(to: &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;UInt8&lt;/span&gt;.&lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;self&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;if&lt;/span&gt; unsafe d &amp;lt; s {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;in&lt;/span&gt; 0..&amp;lt;n { unsafe d[i] = s[i] }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;if&lt;/span&gt; unsafe d &amp;gt; s {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;in&lt;/span&gt; (0..&amp;lt;n).reversed() { unsafe d[i] = s[i] }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;return&lt;/span&gt; unsafe dest
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is the first point where the project stops being ordinary application programming.&lt;br&gt;
Here, I am no longer calling an operating-system API to print a string, but I am implementing the lower-level functions that the language runtime needs in order to exist.&lt;/p&gt;
&lt;h2 class=&#34;heading&#34; id=&#34;describing-the-memory-layout&#34;&gt;
  Describing the memory layout
  &lt;a class=&#34;anchor&#34; href=&#34;#describing-the-memory-layout&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Now that I did implement the Swift code, the linker needs to know where the kernel is loaded and where each part of the executable belongs.&lt;br&gt;
This is the role of &lt;code&gt;linker.ld&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;QEMU’s &lt;code&gt;virt&lt;/code&gt; machine loads an AArch64 kernel at &lt;code&gt;0x40080000&lt;/code&gt; in this setup:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-ld&#34; data-lang=&#34;ld&#34;&gt;ENTRY(_start)

. = 0x40080000;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The linker script then places the boot code first, followed by read-only data, initialized data, uninitialized data, and a stack:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-ld&#34; data-lang=&#34;ld&#34;&gt;.text : {
    KEEP(*(.text.boot))
    *(.text*)
}

.rodata : ALIGN(8) {
    *(.rodata*)
}

.data : ALIGN(8) {
    *(.data*)
}

.bss (NOLOAD) : ALIGN(16) {
    __bss_start = .;
    *(.bss*)
    *(COMMON)
    __bss_end = .;
}

.stack (NOLOAD) : ALIGN(16) {
    . += 0x20000;
    __stack_top = .;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The assembly code uses the &lt;code&gt;__stack_top&lt;/code&gt; symbol to initialize the stack pointer.&lt;br&gt;
The stack is currently &lt;em&gt;128 kB&lt;/em&gt;, which is an &lt;strong&gt;unreasonable&lt;/strong&gt; amount for a kernel that only prints one sentence, but it gives Swift some room to call functions while this project is still experimental.&lt;/p&gt;
&lt;p&gt;Finally, the script explicitly places the ELF metadata sections.
This avoids the orphan-section errors from the first linker attempt:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-ld&#34; data-lang=&#34;ld&#34;&gt;/DISCARD/ : {
    *(.comment)
    *(.debug*)
    *(.eh_frame*)
    *(.swift_*)
}

.symtab : { *(.symtab) }
.strtab : { *(.strtab) }
.shstrtab : { *(.shstrtab) }
&lt;/code&gt;&lt;/pre&gt;&lt;h2 class=&#34;heading&#34; id=&#34;hello-embedded-swift&#34;&gt;
  Hello, Embedded Swift
  &lt;a class=&#34;anchor&#34; href=&#34;#hello-embedded-swift&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Now, let&amp;rsquo;s build it&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt; swift build --triple aarch64-none-none-elf --toolset toolset.json --build-system native
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;, launched with QEMU:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt; qemu-system-aarch64 -machine virt -cpu cortex-a57 -nographic -kernel .build/aarch64-none-none-elf/debug/kernel
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and&amp;hellip;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Hello, Embedded Swift 😊
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then it keeps running forever, because the kernel is trapped in its infinite loop.&lt;/p&gt;
&lt;p&gt;This is not close to a useful kernel, but it is a real AArch64 ELF executable.&lt;br&gt;
It starts by an assembly entry point, links without a standard library, and it calls Swift code on top of a manually configured stack.&lt;/p&gt;
&lt;p&gt;For a first hello world, this is already enough.&lt;/p&gt;
&lt;h2 class=&#34;heading&#34; id=&#34;what-comes-next&#34;&gt;
  What comes next?
  &lt;a class=&#34;anchor&#34; href=&#34;#what-comes-next&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;The project is intentionally unfinished. The next steps are not implemented yet, but they provide a direction for the rest:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;clear the &lt;code&gt;.bss&lt;/code&gt; section during boot,&lt;/li&gt;
&lt;li&gt;hide the UART register behind a small Swift abstraction (I hardcoded QEMU ones for simplicity),&lt;/li&gt;
&lt;li&gt;understand which allocation features Embedded Swift can support,&lt;/li&gt;
&lt;li&gt;investigate interrupts and timers,&lt;/li&gt;
&lt;li&gt;and eventually replace this infinite loop with something that can schedule actual work.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;At some point, I may also want to experiment with a framebuffer, a real keyboard driver, and a minimal interactive environment. But before building a user interface, I need to understand the machine underneath it.&lt;/p&gt;
&lt;h2 class=&#34;heading&#34; id=&#34;responding-to-a-human&#34;&gt;
  Responding to a human
  &lt;a class=&#34;anchor&#34; href=&#34;#responding-to-a-human&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;For now, the machine says hello.
Printing a message is nice, but it is still a one-way conversation.&lt;/p&gt;
&lt;p&gt;The PL011 UART also has a receive register.&lt;br&gt;
Before reading from it, I need to check its flag register.
Bit 4, called &lt;code&gt;RXFE&lt;/code&gt;, tells us whether the receive FIFO is empty.&lt;br&gt;
If it is empty, we wait.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic;text-decoration:underline&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;QEMU_UART_FLAG_REGISTER&lt;/span&gt;: &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;UInt&lt;/span&gt; = 0x0900_0018
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@unsafe &lt;span style=&#34;font-weight:bold;font-style:italic;text-decoration:underline&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;readChar&lt;/span&gt;() -&amp;gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;UInt8&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;font-style:italic;text-decoration:underline&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;uart&lt;/span&gt; = unsafe &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;UnsafeMutablePointer&lt;/span&gt;&amp;lt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;UInt8&lt;/span&gt;&amp;gt;(bitPattern: QEMU_UART_REGISTER)!
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;font-style:italic;text-decoration:underline&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;flags&lt;/span&gt; = unsafe &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;UnsafeMutablePointer&lt;/span&gt;&amp;lt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;UInt8&lt;/span&gt;&amp;gt;(bitPattern: QEMU_UART_FLAG_REGISTER)!
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// The RXFE bit is set while the receive FIFO is empty.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;while&lt;/span&gt; unsafe (flags.pointee &amp;amp; 0x10) != 0 {}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;return&lt;/span&gt; unsafe uart.pointee
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is &lt;strong&gt;polling&lt;/strong&gt;. The CPU repeatedly checks the UART until a character arrives and it is a very &lt;strong&gt;inefficient&lt;/strong&gt; way to do something like that.
A real kernel would eventually use interrupts, but it is simple enough for a first implementation.&lt;/p&gt;
&lt;p&gt;The kernel can now echo characters back to the terminal:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@c
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic;text-decoration:underline&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;kernel_main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Swift kernel ready.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;font-style:italic;text-decoration:underline&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt; = unsafe putchar(62)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;font-style:italic;text-decoration:underline&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt; = unsafe putchar(32)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;font-style:italic;text-decoration:underline&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ignoreLineFeed&lt;/span&gt; = &lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;while&lt;/span&gt; &lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;true&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold;font-style:italic;text-decoration:underline&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;character&lt;/span&gt; = unsafe readChar()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;if&lt;/span&gt; character == 13 {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold;font-style:italic;text-decoration:underline&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt; = unsafe putchar(10)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold;font-style:italic;text-decoration:underline&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt; = unsafe putchar(62)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold;font-style:italic;text-decoration:underline&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt; = unsafe putchar(32)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ignoreLineFeed = &lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;if&lt;/span&gt; character == 10 {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;if&lt;/span&gt; !ignoreLineFeed {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold;font-style:italic;text-decoration:underline&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt; = unsafe putchar(10)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold;font-style:italic;text-decoration:underline&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt; = unsafe putchar(62)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold;font-style:italic;text-decoration:underline&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt; = unsafe putchar(32)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ignoreLineFeed = &lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold;font-style:italic;text-decoration:underline&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt; = unsafe putchar(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;CInt&lt;/span&gt;(character))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ignoreLineFeed = &lt;span style=&#34;font-weight:bold;text-decoration:underline&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The numbers &lt;code&gt;62&lt;/code&gt; and &lt;code&gt;32&lt;/code&gt; are simply the ASCII codes for &lt;code&gt;&amp;gt;&lt;/code&gt; and a space.
I could create a small string-writing abstraction, but for the moment I prefer to keep the mechanism visible.&lt;/p&gt;
&lt;p&gt;Running the same QEMU command now gives us a prompt:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Swift kernel ready.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt; hello kernel
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hello kernel
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt; 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is still a very small feature.&lt;br&gt;
There is no line editor, no backspace handling, no command parser&amp;hellip; and the CPU is busy waiting for every character because it uses polling instead of interrupts.&lt;/p&gt;
&lt;p&gt;For a program that started with &lt;code&gt;print(&amp;quot;Hello... world?&amp;quot;)&lt;/code&gt;, this feels like a good place to stop and start writing a TODO list to improve all of that.&lt;/p&gt;
&lt;p&gt;The full code is available on my &lt;a href=&#34;https://carette.xyz/posts/free-of-github/&#34;&gt;private git space&lt;/a&gt;: &lt;a href=&#34;https://git.carette.xyz/k0pernicus/swift-kernel&#34;&gt;https://git.carette.xyz/k0pernicus/swift-kernel&lt;/a&gt;.&lt;br&gt;
Have fun!&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>
