We are two geeks from America who wanted to have some fun with the idea of making our own distro, this led to creating two seperate distros, eventually we colaberated on an operating system based on Ubuntu.
-
-
-
-
-
-
-
-
-
-
-
-
Why Dragon Linux?
-
-
-
-
-
-
-
-
-
-
-
-
-
Dragon Linux is a distro of Mint, meaning its easy enough for new users to go into it, but we gave it the customization we thought it needed to become an OS that we, at the FREEDOM-HQ team, would use on our daily life.
-
-
-
-
-
-
-
-
-
-
-
-
What do we offer?
-
-
-
-
-
-
-
-
-
-
-
-
-
Dragon Linux offers an easy to use, pretty and comfortable graphic enviroment in which you will find pre-installed apps, as well as ARM64 Support.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Previous
-
-
- Next
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
The Dragon Linux project has been a reality since October 2018. Since then, we have grown into a big community that you are invited to be a part of in our Discord channel.
-
-
-
-
-
-
-
-
-
-
-
-
FAQ.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Why did you create Dragon Linux?
-
Minimum specs required
-
Recommended required specs
-
How did you create Dragon Linux?
-
XFCE version? Arch version?
-
ARM version?
-
How can I help with the project?
-
-
-
Why did you create Dragon Linux?
-
We really did this as a school project on our free time, cause we wanted to create an OS that was to our exact liking, but then we invested more and more time in the project like, built the website, released the OS on the internet just to see if people liked it, etc and as it was a good name to play with, we were lucky enough to find people who liked it
-
Minimum specs required
-
1.5 GHz processor 2 GB of system memory (RAM) 60 GB of disk space
-
Recommended required specs
-
4GB or more of RAM 64-bit capable Intel and AMD processors UEFI PCs booting in CSM mode. Modern Intel-based Apple Macs
-
How did you create Dragon Linux?
-
We created Dragon Linux by using cubic, which is a GUI wizard to create a customized Live ISO image for Ubuntu based distributions.
you can try cubic yourself by installing it into your linux OS. https://launchpad.net/cubic
-
XFCE version? Arch version?
-
Our desktop version uses the cinnamon DE. As of today, we have no intentions on making more than one version of Dragon Linux, as we feel it would affect the general quality.
-
ARM version?
-
We do not have a ARM based version out as of writing.
-
How can I help with the project?
-
Suggestions are always welcomed! you can join our discord community and mesagge us there, if you want to contribute more directly into the project, feel free to add us on discord so we can talk about it.
+
+And since the GPU power management is handled by the firmware, all that just works. I tested Xonotic at 1080p inside a GNOME session, and the estimated battery runtime was over 8 hours! 🚀
+
+What about Vulkan support? Don't worry... [Ella](https://tech.lgbt/@ella) is working on that! ✨✨
+
+
+
+## What's next?
+
+There is still a long road ahead! The UAPI that we are using right now is still a prototype, and there are a lot of new features that need to be added or redesigned in order to support a full Vulkan driver in the future. Since Linux mandates that the UAPI needs to remain stable and backwards compatible across versions (unlike macOS), that means that the kernel driver will not be heading upstream for many months, until we have a more complete understanding of the GPU rendering parameters and have implemented all the new design features needed by Vulkan. The current UAPI also has performance limitations... it can't even run GPU rendering concurrently with CPU processing yet!
+
+And of course there is still a lot of work to do on the userspace side, improving conformance and performance and adding support for more GL extensions and features! Some features like tesselation and geometry shaders are very tricky to implement (since they need to be partially or fully emulated), so don't expect full OpenGL 3.2+ for quite a long time.
+
+But even with those limitations, the drivers can run stable desktops today and performance is improving every week! Wayland runs beautifully smoothly on these machines now, just like the native macOS desktop! Xorg also works well with some improvements I made to the display driver a few days ago, although you can expect tearing and vsync issues due to Xorg design limitations. Wayland is really the future on new platforms! 💫
+
+So where do you get it? We're not quite there yet! Right now the driver stack is complicated to build and install (you need custom m1n1, kernel, and mesa builds), so please wait a little bit longer! We have a few loose ends to tie still... but we hope we can bring it to Asahi Linux as an opt-in testing build before the end of the year! ✨✨
+
+If you're interested in following my work on the GPU, you can follow me at [@lina@vt.social](https://vt.social/@lina) or subscribe to my [YouTube channel](https://youtube.com/AsahiLina)! Tomorrow I'm going to be working on figuring out the power consumption calculations for the M1 Pro/Max/Ultra and M2, and I hope to see you there! ✨
+
+If you want to support my work, you can donate to marcan's Asahi Linux support funds on [GitHub Sponsors](http://github.com/sponsors/marcan) or [Patreon](https://patreon.com/marcan), which helps me out too! And if you're looking forward to a Vulkan driver, check out Ella's [GitHub Sponsors](https://github.com/sponsors/Ella-0) page! Alyssa doesn't take donations herself, but she'd love it if you donate to a charity like the [Software Freedom Conservancy](https://sfconservancy.org/) instead. (Although maybe one day I'll convince her to let me buy her an M2... ^^;;)
diff --git a/content/blog/2022/12/07-gpu-drivers-now-in-asahi-linux.md b/content/blog/2022/12/07-gpu-drivers-now-in-asahi-linux.md
new file mode 100644
index 0000000..c3afe00
--- /dev/null
+++ b/content/blog/2022/12/07-gpu-drivers-now-in-asahi-linux.md
@@ -0,0 +1,98 @@
++++
+date = "2022-12-07T14:50:00+09:00"
+draft = false
+title = "Apple GPU drivers now in Asahi Linux"
+slug = "gpu-drivers-now-in-asahi-linux"
+author = "Alyssa Rosenzweig & Asahi Lina"
++++
+
+Hello everyone! We're excited to announce our first public Apple Silicon GPU driver release!
+
+We've been working hard over the past two years to bring this new driver to everyone, and we're really proud to finally be here. This is still an alpha driver, but it's already good enough to run a smooth desktop experience and some games.
+
+Read on to find out more about the state of things today, how to install it (it's an opt-in package), and how to report bugs!
+
+
+
+# Status
+
+This release features work-in-progress OpenGL 2.1 and OpenGL ES 2.0 support for all current Apple M-series systems. That's enough for hardware acceleration with desktop environments, like GNOME and KDE. It's also enough for older 3D games, like Quake3 and Neverball. While there's always room for improvement, the driver is fast enough to run all of the above at 60 frames per second at 4K.
+
+Please note: these drivers have not yet passed the OpenGL (ES) conformance tests. There will be bugs!
+
+What's next? Supporting more applications. While OpenGL (ES) 2 suffices for some applications, newer ones (especially games) demand more OpenGL features. OpenGL (ES) 3 brings with it a slew of new features, like multiple render targets, multisampling, and transform feedback. Work on these features is well under way, but they will each take a great deal of additional development effort, and all are needed before OpenGL (ES) 3.0 is available.
+
+What about Vulkan? We're working on it! Although we're only shipping OpenGL right now, we're designing with Vulkan in mind. Most of the work we're putting toward OpenGL will be reused for Vulkan. We estimated that we could ship working OpenGL 2 drivers much sooner than a working Vulkan 1.0 driver, and we wanted to get hardware accelerated desktops into your hands as soon as possible. For the most part, those desktops use OpenGL, so supporting OpenGL first made more sense to us than diving into the Vulkan deep end, only to use Zink to translate OpenGL 2 to Vulkan to run desktops. Plus, there is a large spectrum of OpenGL support, with OpenGL 2.1 containing a fraction of the features of OpenGL 4.6. The same is true for Vulkan: the baseline Vulkan 1.0 profile is roughly equivalent to OpenGL ES 3.1, but applications these days want Vulkan 1.3 with tons of extensions and "optional" features. Zink's "layering" of OpenGL on top of Vulkan isn't magic: it can only expose the OpenGL features that the underlying Vulkan driver has. A baseline Vulkan 1.0 driver isn't even enough to get OpenGL 2.1 on Zink! Zink itself advertises support for OpenGL 4.6, but of course that's only when paired with Vulkan drivers that support the equivalent of OpenGL 4.6... and that gets us back to a tremendous amount of time and effort.
+
+When will OpenGL 3 support be ready? OpenGL 4? Vulkan 1.0? Vulkan 1.3? In community open source projects, it's said that every time somebody asks when a feature will be done, it delays that feature by a month. Well, a lot of people have been asking...
+
+At any rate, for a sneak peek... here is SuperTuxKart's deferred renderer running at full speed, making liberal use of OpenGL ES 3 features like multiple render targets~
+
+
+
+# Anatomy of a GPU driver
+
+Modern GPUs consist of many distinct "layered" parts. There is...
+
+* a memory management unit and an interface to submit memory-mapped work to the hardware
+* fixed-function 3D hardware to rasterize triangles, perform depth/stencil testing, and more
+* programmable "shader cores" (like little CPUs with bespoke instruction sets) with work dispatched by the fixed-function hardware
+
+This "layered" hardware demands a "layered" graphics driver stack. We need...
+
+* a kernel driver to map memory and submit memory-mapped work
+* a userspace driver to translate OpenGL and Vulkan calls into hardware-specific data structures in graphics memory
+* a compiler translating shading programming languages like GLSL to the hardware's instruction set
+
+That's a lot of work, calling for a team effort! Fortunately, that layering gives us natural boundaries to divide work among our small team.
+
+* [Alyssa Rosenzweig](https://social.treehouse.systems/@alyssa) is writing the OpenGL driver and compiler.
+* [Asahi Lina](https://vt.social/@lina) is writing the kernel driver and helping with OpenGL.
+* [Dougall Johnson](https://mastodon.social/@dougall) is reverse-engineering the instruction set with Alyssa.
+
+Meanwhile, [Ella Stanforth](https://tech.lgbt/@ella) is working on a Vulkan driver, reusing the kernel driver, the compiler, and some code shared with the OpenGL driver.
+
+Of course, we couldn't build an OpenGL driver in under two years just ourselves. Thanks to the power of free and open source software, we stand on the shoulders of FOSS giants. The compiler implements a "NIR" backend, where NIR is a powerful intermediate representation, including GLSL to NIR translation. The kernel driver users the "Direct Rendering Manager" (DRM) subsystem of the Linux kernel to minimize boilerplate. Finally, the OpenGL driver implements the "Gallium3D" API inside of [Mesa](https://mesa3d.org/), the home for open source OpenGL and Vulkan drivers. Through Mesa and Gallium3D, we benefit from thirty years of OpenGL driver development, with common code translating OpenGL into the much simpler Gallium3D. Thanks to the incredible engineering of NIR, Mesa, and Gallium3D, our ragtag team of reverse-engineers can focus on what's left: the Apple hardware.
+
+# Installation instructions
+
+To get the new drivers, you need to run the `linux-asahi-edge` kernel and also install the `mesa-asahi-edge` Mesa package.
+
+```
+$ sudo pacman -Syu
+$ sudo pacman -S linux-asahi-edge mesa-asahi-edge
+$ sudo update-grub
+```
+
+Since only one version of Mesa can be installed at a time, pacman will prompt you to replace `mesa` with `mesa-asahi-edge`. This is normal!
+
+We also recommend running Wayland instead of Xorg at this point, so if you're using the KDE Plasma environment, make sure to install the Wayland session:
+
+```
+$ sudo pacman -S plasma-wayland-session
+```
+
+Then reboot, pick the Wayland session at the top of the login screen (SDDM), and enjoy! You might want to adjust the screen scale factor in *System Settings → Display and Monitor* (Plasma Wayland defaults to 100% or 200%, while 150% is often nicer). If you have "Force font DPI" enabled under *Appearance → Fonts*, you should disable that (it is saved separately for Wayland and Xorg, and shouldn't be necessary on Wayland sessions). Log out and back in for these changes to fully apply.
+
+Xorg and Xorg-based desktop environments should work, but there are a few known issues:
+
+* Expect screen tearing (this might be fixed [soon](https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1006))
+* VSync does not work (some KDE animations will be too fast, and GL apps will not limit their FPS even with VSync enabled). This is a limitation of Xorg on the Apple DCP display controllers, which do not support VBlank interrupts.
+* There are still driver bugs triggered by Xorg/KWin. We're looking into this.
+
+The `linux-asahi-edge` kernel can be installed side-by-side with the standard `linux-asahi` package, but both versions should be kept in sync, so make sure to always update your packages together! You can always pick the `linux-asahi` kernel in the GRUB boot menu, which will disable GPU acceleration and the DCP display driver.
+
+When the packages are updated in the future, it's possible that graphical apps will stop starting up after an update until you reboot, or they may fall back to software rendering. This is normal. Until the UAPI is stable, we'll have to break compatibility between Mesa and the kernel every now and then, so you will need to reboot to make things work after updates. In general, if apps *do* keep working with acceleration after any particular Mesa update, then it's probably safe not to reboot, but you should still do it to make sure you're running the latest kernel!
+
+# Reporting bugs
+
+Since the driver is still in development, there are lots of known issues and we're still working hard on improving conformance test results. Please don't open new bugs for random apps not working! It's still the early days and we know there's a lot of work to do. Here's a quick guide of how to report bugs:
+
+* If you find an app that does not start up at all, please don't report it as a bug. Lots of apps won't work because they require a newer GL version than what we support. Please set the `LIBGL_ALWAYS_SOFTWARE=1` environment variable for those apps to fall back to software rendering. If it is a popular app that is part of the Arch Linux ARM repository, you can make a comment on [this issue](https://github.com/AsahiLinux/linux/issues/73) instead, so we can add Mesa quirks to workaround.
+* If you run into issues caused by `linux-asahi-edge` unrelated to the GPU, please add a comment to [this issue](https://github.com/AsahiLinux/linux/issues/70). This includes display output issues! (Resolutions, backlight control, display power control, etc.)
+* If the GPU locks up and all GPU apps stop working, run `asahi-diagnose` (for example, from an SSH session), open a new bug on [AsahiLinux/linux](https://github.com/AsahiLinux/linux), attach the file generated by that command, and tell us what you were doing that caused the lockup.
+* For other GPU issues (rendering glitches, apps that crash after starting up correctly, and things like that), run `asahi-diagnose` and make a comment on [this issue](https://github.com/AsahiLinux/linux/issues/72), attaching the file generated by that command. Don't forget to tell us about your environment!
+* In the future, if a driver update causes a regression (rendering problems or crashes for apps that previously worked properly), you can open a bug [directly in the Mesa tracker](https://gitlab.freedesktop.org/asahi/mesa/-/issues).
+
+We hope you enjoy our driver! Remember, things are still moving quickly, so make sure to update your packages regularly to get updates and bug fixes!
+
diff --git a/content/blog/2023/03/20-road-to-vulkan.md b/content/blog/2023/03/20-road-to-vulkan.md
new file mode 100644
index 0000000..9547eee
--- /dev/null
+++ b/content/blog/2023/03/20-road-to-vulkan.md
@@ -0,0 +1,274 @@
++++
+date = "2023-03-20T23:50:00+09:00"
+draft = false
+title = "Paving the Road to Vulkan on Asahi Linux"
+slug = "road-to-vulkan"
+author = "Asahi Lina"
++++
+
+Hello everyone, Asahi Lina here!✨
+
+As you probably know, I've been working together with the rest of the Asahi Linux team on open source GPU drivers for Apple Silicon platforms. It's been a wild ride! Just at the end of last year we [released](https://asahilinux.org/2022/12/gpu-drivers-now-in-asahi-linux/) the first version of our drivers, after many months of reverse engineering and development. But that was only the beginning...
+
+Today we're releasing a big update to our GPU drivers for Asahi Linux, so I wanted to talk to you about what we've been working on since then, and what's next!
+
+If this is your first time reading about our GPU adventures, you might want to check out my [Tales of the M1 GPU](/2022/11/tales-of-the-m1-gpu/) article first, which covers what I worked on last year! Also don't miss Alyssa's amazing series of articles on [her website](https://rosenzweig.io/), which goes all the way back to January 2021! ^^
+
+And if this is too long, feel free to [jump to the end](#conclusions) to learn what this all means for Asahi Linux!
+
+{{< captioned caption="Xonotic running at 800+ FPS on an Apple M2" >}}
+
+{{< /captioned >}}
+
+## What's a UAPI?
+
+
+
+In every modern OS, GPU drivers are split into two parts: a userspace part, and a kernel part. The kernel part is in charge of managing GPU resources and how they are shared between apps, and the userspace part is in charge of converting commands from a graphics API (such as OpenGL or Vulkan) into the hardware commands that the GPU needs to execute.
+
+Between those two parts, there is something called the Userspace API or "UAPI". This is the interface that they use to communicate between them, and it is specific to each class of GPUs! Since the exact split between userspace and the kernel can vary depending on how each GPU is designed, and since different GPU designs require different bits of data and parameters to be passed between userspace and the kernel, each new GPU driver requires its own UAPI to go along with it.
+
+On macOS, since Apple controls both the kernel driver and the userspace Metal/GL driver, and since they are always updated in sync as part of new macOS versions, the UAPI can change whenever they want. So if they need a new feature to support a new GPU, or they need to fix a bug or a design flaw, or make a change to improve performance, that's not an issue! They don't have to worry too much about getting the UAPI right, since they can always change it later. But things aren't so easy on Linux...
+
+The Linux kernel has a super strict *userspace API stability guarantee*. That means that newer Linux kernel versions must support the same APIs that older ones do, and older apps and libraries must continue working with newer kernels. Since graphics UAPIs can be quite complicated, and often need to change as new GPU support is added to any given driver, this makes it very important to have a good UAPI design! After all, once a driver is in the upstream Linux kernel, you can't break compatibility with the old UAPI, ever. If you make a mistake, you're stuck with it forever. This makes UAPI design a very difficult problem! The Linux DRM subsystem even has [special rules](https://dri.freedesktop.org/docs/drm/gpu/drm-uapi.html#open-source-userspace-requirements) for GPU UAPIs to try to minimize these issues...
+
+## UAPI baby steps
+
+When I started working on the driver, my first goal was to figure out how the GPU and its firmware worked, and how to talk to them (the "Firmware API" in the diagram). First I wrote a demo in Python that ran remotely over USB and could render single frames, and then I realized I wanted to try hooking up Alyssa's Mesa driver to it directly so I could run real demos and test apps. Mesa already had a testing tool called "drm-shim" which can "fake" the Linux DRM UAPIs, so all I had to do was plug a Python interpreter into it! But we didn't have a UAPI yet for our driver...
+
+So I copied and pasted the [Panfrost](https://docs.mesa3d.org/drivers/panfrost.html) UAPI, simplified it a bit, and ran with that! Since drm-shim isn't a real Linux kernel, and since my Python driver was just a demo all running in a single process, there was no parallelism possible: when the app submits a command to the GPU, the Python driver runs it immediately, and doesn't return to the app until everything completes. This didn't matter at all at the time, since running everything over a USB connection was a much bigger bottleneck!
+
+As I reverse engineered more things about the GPU, I figured out how to do parallelism properly, and I had several Python-based demos that could run several things on the GPU at once. And so, when it came time to write the real Linux driver in Rust, I mostly knew everything I needed to design it to do that! The Rust driver's core supported running multiple things at once, and indeed with our release in December, you can run multiple apps that use the GPU at once and they can (in principle) submit work to the GPU in parallel, without blocking each other. But... I already had the "demo" UAPI hooked up into Mesa, so at the time... I left it as-is!
+
+What was the issue with that UAPI? Just like the Python demo, the whole GPU rendering process was synchronous: when an app submitted work to the GPU it would be queued to be executed by the firmware, then executed, and only when everything was complete would the UAPI call return back to the app. That means that the CPU and the GPU couldn't process anything in parallel within a single app! Not only that, there is some latency to going back and forth between the CPU and the GPU, which reduced performance even more...
+
+
+
+Thankfully, both the GPU and the CPU are so fast that even with this terrible design, things still ran fast enough to give us a usable desktop at 60FPS. 🚀
+
+But this clearly wouldn't do, and it would be a terrible design to try to upstream, so we had to come up with something better.
+
+## GPU Synchronization
+
+Once you start running things in parallel, you run into the issue of how to keep everything synchronized. After all, after the CPU submits work to the GPU, it might actually have to wait for it to finish at some point before it can use the results. Not only that, different bits of work submitted to the GPU often depend on each other! These dependencies can even extend across apps: a game can queue multiple render passes that depend on each other in a complex way, and then the final scene has to be passed to the Wayland compositor, which can only begin compositing once the scene is done rendering. Even more, the Wayland compositor has to queue a page flip on the display controller so it can show the new frame, but that can only happen once the frame is done rendering!
+
+
+
+All of those things have to happen in the right order for everything to work right, and the UAPI must provide a mechanism for it. As graphics APIs have changed over the years, so has the way this is done. Traditionally, UAPIs were based on the OpenGL "implicit sync" model...
+
+## Implicit Sync
+
+The implicit sync model is based on the idea that synchronization is tied to buffers, which are things like textures and framebuffers. When work is submitted to the GPU, the kernel driver tracks what buffers it reads from and what buffers it writes to. If it is reading or writing from/to any buffers that are being (or will be) written to by previously submitted GPU work, the driver makes sure that it doesn't start executing until those jobs are complete. Internally, this works by having each buffer contain one or more *DMA fences*, which track readers and writers and allow readers to block on prior writers.
+
+This works! It means the app developer doesn't really have to care about synchronization much: they just render to a texture, then use it later, and the driver makes it look like everything is executing sequentially by tracking the dependency. This works across apps too, and even between the GPU and the display controller.
+
+Unfortunately, this model is not very efficient. It means that the kernel needs to keep track of every single GPU buffer that all render jobs might use! Say a game uses 100 textures: that means that every single time it renders a scene, the kernel has to check to make sure nobody is writing to those textures, and mark them as being read from. But why would anyone be writing to them? After all, most textures are usually loaded into memory once and never touched again. But the kernel doesn't know that...
+
+This model is supported by all Linux mainline GPU drivers today! Some drivers have since added support for explicit sync (like amdgpu), but they still have support for full implicit sync under the hood. Remember the UAPI stability rules...?
+
+## Explicit Sync
+
+Then along came Vulkan, and said there was a better way. In Vulkan, there is no implicit synchronization of buffers. Instead, the app developer is responsible for manually keeping track of dependencies between things they submit to the GPU, and Vulkan provides several tools to tell the system what it needs: barriers, events, fences, and timeline semaphores.
+
+Vulkan is pretty complicated, so we won't go into all the details... but essentially, these tools give the app fine-grained control over what has to wait for what and when. There is no implicit buffer synchronization any more, which is great! The kernel driver no longer needs to keep track of possibly dozens or hundreds of buffers, but instead only the very specific sync requirements that the app requests.
+
+(*By the way, Metal supports both explicit sync and implicit sync for some reason, but I digress...*)
+
+Under the hood, Linux implements explicit sync using a standard mechanism called *sync objects*. Each sync object is basically a container for a completion, which is actually a DMA fence. If you've ever used async programming frameworks, you've probably heard of *promises*. DMA fences are basically the GPU version of a *promise*! Sync objects are actually originally [an OpenGL concept](https://www.khronos.org/opengl/wiki/Sync_Object), but they have since been adapted and extended to work with Vulkan's more complex requirements.
+
+In the explicit sync world, when an app submits GPU work to the kernel, it gives it a list of *input* sync objects and a list of *output* sync objects. The kernel driver checks all the input sync objects and registers their fences as dependencies of the GPU work. Then it creates a new (pending) completion fence for the work, and inserts it into the output sync objects (remember, sync objects are *containers* for a fence, so they can be replaced). The driver then queues the work for execution, and returns immediately to userspace. Then, in the background, the work is only allowed to execute once all dependency fences have been signaled, and it then signals its own completion fence when it's done. Phew! A nice, clean, and modern kernel UAPI for synchronization!
+
+Except there's a problem...
+
+## Trouble with Windowing Systems
+
+Within a single app, Vulkan lets you take care of synchronization. But what about synchronizing across apps, like when a game sends a frame to a Wayland compositor? This could use sync objects... but Wayland was almost 10 years old by the time Linux sync objects were invented!
+
+Of course, all existing *window system integration* standards in desktop Linux assume implicit sync. We could add explicit sync to them, but that would break backwards compatibility...
+
+What all existing Linux drivers do is... to just support both. You still give the kernel driver a list of buffers you read/write to and from, and that can exclude things like textures that the driver knows are not shared with any other process. Then the kernel implicitly synchronizes with those buffers, and explicitly synchronizes with the sync objects. That works, but again it makes drivers more complicated...
+
+What we need is a way to bridge between the implicit sync and explicit sync worlds, without having to reinvent the wheel for every driver. Thankfully, the Linux DRM subsystem developers have been hard at work solving this, and just a few months ago we finally had a solution!
+
+## Bridging both worlds
+
+Remember how I said that implicit sync works by using DMA fences attached to buffers, and explicit sync works by using DMA fences inside sync objects?
+
+Just a few months before our Asahi driver release last year, on October 2022, Linux 6.0 was released. And with it came two new generic DRM APIs: one to import a DMA fence into a DMA-BUF, and one to export it out of it.
+
+Together with the existing generic sync object APIs, this lets us close the gap entirely! Userspace apps can now take a fence out of a DMA-BUF (a buffer shared with another process), turn it into a sync object for a GPU job to wait on, then take an output sync object for that job, and insert its fence into another DMA-BUF that can be shared with another process.
+
+Faith Ekstrand wrote [an excellent article](https://www.collabora.com/news-and-blog/blog/2022/06/09/bridging-the-synchronization-gap-on-linux/) covering this if you want more details! She has also been an amazing mentor and I couldn't have figured out all this UAPI design stuff without her help.
+
+Great! This solves all our problems! But as they say, the devil is in the details...
+
+## OpenGL wants a word with you...
+
+Explicit sync is great and all, but we don't have a Vulkan driver yet, we have an OpenGL driver. How do we make that work?
+
+OpenGL is very much based on the implicit sync model. So to make an OpenGL driver work with an explicit sync UAPI, the driver has to take care of bridging between both worlds. Of course, we could go back to importing/exporting fences on every single buffer, but that would be even slower than doing implicit sync in the kernel in the first place...
+
+There's also an even bigger problem: Even ignoring buffer sync issues, in an implicit sync world the kernel keeps track of all buffers needed by the GPU. But in an explicit sync world that doesn't happen! What this means is that an app could render using a texture, then free and destroy the texture... and in an explicit sync driver, that would mean that the texture is deallocated immediately, even if the GPU is still using it! In Vulkan that would be an app bug, but in OpenGL that has to work...
+
+Explicit sync in Mesa has mostly been used for Vulkan drivers, but since pure explicit sync Linux GPU drivers don't exist in mainline yet, there are no OpenGL (Gallium) drivers in Mesa that do this! They mostly just use the legacy implicit sync path... so I had no code to reference and I had to figure out how to make this work all on my own ^^;;.
+
+And so I set out to find a way to make explicit sync work with the Mesa driver that Alyssa and I had been working on. Thankfully, it turned out not to be too much of a refactor!
+
+You see, in order to have good performance on tile-based mobile GPUs, you can't just map OpenGL directly to the hardware. On tile-based GPUs, things aren't rendered directly into framebuffers *immediately*. Instead, a whole scene of geometry is collected first, then it runs through vertex shaders, gets split up into tiles based on screen position, and is finally rendered tile by tile in super fast tile memory before being written out to the framebuffer. If you split up your rendering into many tiny passes, that means loading and saving the framebuffer every time, and that is very slow on these GPUs! But OpenGL lets apps switch around framebuffers as often as they want, and many apps and games do this all the time... if we just flushed the rendering every time that happened, that would be very slow!
+
+So, to deal with this, Alyssa developed a *batch tracking* system for the Panfrost driver (based on Rob Clark's original implementation for Freedreno), and later added a similar system to the Asahi driver. The idea is that instead of sending work to the GPU immediately, you collect it into a *batch*. If the app switches to another framebuffer, you leave the batch as-is, and create a new batch. If the app switches back to the original framebuffer, you just switch batches again and keep appending work to the original batch. Then, when you actually need to render everything, you submit the complete batches to the hardware.
+
+Of course, there's an issue here... what if the app is trying to read from a framebuffer it previously rendered to? If we haven't submitted that batch yet, it will get the wrong data... so the batch tracking system keeps track of *readers* and *writers* for each buffer, and then flushes batches to the GPU any time their output is needed for the current batch.
+
+... wait a minute, doesn't that kinda sound like implicit sync all over again?
+
+It turns out the driver already had all the core bits and pieces I needed! Batch tracking can:
+
+* Track multiple bits of GPU work that are independent at the same time, and
+* Track their dependencies based on buffers read/written, and
+* Keep buffers they need alive until the batch is submitted to the GPU
+
+I just had to extend the batch tracking system so that, instead of only tracking GPU work that *hasn't* been submitted, it also tracks work which *has* been submitted to the kernel but *hasn't completed* yet! Then the existing reader/writer machinery could be used to figure out what buffers are read and written. Since batches are submitted to the GPU in a single queue and execute in order, we mostly don't have to worry about synchronizing between batches as long as we add a full GPU barrier before each batch.
+
+This ended up being a medium size, but not too unwieldy [commit](https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21620/diffs?commit_id=04387269dd3f054e2d1c9d99dc5650085dd417e9). Most of the changes were in the batch tracking code, and it was mostly just extending the existing code to handle the idea of batches that aren't *active* but rather *submitted*. Then we use the existing Linux sync object APIs to figure out when batches are actually complete, and only then finally clean up the batches. And with that, explicit sync worked!
+
+Well... kind of. It worked for surfaceless (offscreen) render tests, but we still had that pesky issue of how to handle implicit sync for buffers shared with other apps...
+
+## Implicit sync's many sharp edges...
+
+There actually *is* one driver I could reference. While it is not merged yet, Intel's new [Xe kernel driver](https://lore.kernel.org/dri-devel/20221222222127.34560-1-matthew.brost@intel.com/) is also a brand new, pure explicit sync driver, and the [Mesa side](https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20418) adds support for it to the existing Intel Iris driver in Mesa. In fact, the Asahi driver's UAPI is heavily inspired by the Xe one (at Faith's suggestion)!
+
+The way these two GPUs work and how the drivers are designed is too different to use Xe/Iris as an example for how to make the internal batch tracking work with explicit sync within the driver, but we can at least take a look at how it handles implicit sync with shared buffers. The idea turned out to be pretty simple:
+
+* Before submitting work to the GPU, look through all the buffers used and find any shared ones, then grab their DMA fences and set them up as input sync objects.
+* After submitting work, take the output sync object, extract its fence, and install it into all shared buffers again.
+
+*Et voilà*! Implicit sync window system integration support!
+
+And then Firefox started crashing on WebGL tests...
+
+## Schrödinger's Buffer Sharing
+
+As part of the new UAPI design, the driver is supposed to tell the kernel when buffers might be shared. The kernel still needs to know about all buffers that an app has allocated, and due to corner cases in memory management (that aren't even implemented yet in our driver, but will be), still needs to lock them when you do stuff with the GPU. So on existing drivers like i915 you end up with the kernel locking possibly thousands of buffers when GPU work is sent, even if they aren't all used by the GPU! This is bad, so the Xe UAPI has an optimization that I carried over to Asahi: if you mark a buffer as not shared, the kernel groups it with all the other non-shared buffers and they share the same lock. That means that you can never ever share those buffers between processes, and the kernel prevents this. The Gallium driver layer in Mesa has a flag for whether buffers are potentially shared that gets passed in at creation time, so that's easy, right?
+
+Except this is legal in OpenGL:
+
+1. `glTexStorage2D(...)` (Make a texture, allocate storage, upload data)
+2. `eglCreateImageKHR(...)` (Turn the texture into an EGL image)
+3. `eglExportDMABUFImageMESA(...)` (Export it)
+
+There is no way for the OpenGL driver to know that you're going to share a texture at creation time. It looks like it's not shared, and then it's suddenly shared. Oops!
+
+It turns out this was an existing problem in Mesa for [other reasons](https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13154) unrelated to explicit sync, and there is a Gallium callback called `flush_resource` where drivers are supposed to make resources shareable. So I [added some code](https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21620/diffs?commit_id=c41f10eb9ebf82f9d37f83ec0a182215600327cd) there to re-allocate and copy the buffer as shareable. It's not the fastest solution, and we might change it in the future, but it works for now...
+
+All done, right?
+
+```
+21:05 lina: still have magenta rectangles in supertuxkart with latest branches
+21:20 still at startup in one of two starts? was fine in the stream under plasma/wayland
+21:21 yes
+21:22 in sway if it matters
+21:22 also saw it sometimes in nautilus
+21:23 right, can't reproduce in gnome
+21:23 but can reproduce easily in sway
+21:23 so ... more WSI junk
+21:23 and yeah goes away with ASAHI_MESA_DEBUG=sync
+21:24 so... some WSI sync issue that only reproduces with sway
+21:24 and supertuxkart is the easiest reproduce
+03:20 alyssa: Only on startup and only on sway? Hmm... that's starting to sound like something that shouldn't block release at this point ^^;;
+03:20 Does it go away with ASAHI_MESA_DEBUG=sync only for stk, or for all of sway?
+03:26 lina: setting =sync for stk but not sway is enough
+03:27 but it's not just supertuxkart that's broken, it's everything, this is just the easiest reproducer
+03:27 so yes, this is a regression and absolutely does block release
+```
+
+## Schrödinger's Buffer Sharing, Part 2...
+
+Long story short, it turns out that apps can also do this:
+
+1. Create a framebuffer (possibly shareable), but don't share it yet.
+2. Render stuff into the buffer.
+3. Share it.
+
+When we submit the rendering command, it doesn't look like it's shared yet, so the driver doesn't do the implicit sync dance... and then when the app shares it, it's too late, and it doesn't have the right fence attached to it. Whoever is on the other side will try to use the buffer, and won't wait until the render is complete. Whoops!
+
+I had to add a mechanism that keeps track of sync object IDs for all submitted but not complete batches, and attaches them to all buffers that are written. Then if those buffers are shared before we know those batches are complete, we can retroactively attach the fences.
+
+Interestingly, when I brought this up with the Intel folks working on the Xe merge request... they hadn't heard of this before! It looks like their driver might have the same bug... I guess they might want to start testing with Sway ^^;;
+
+Are we done yet? Mostly, though there are still bugs to squash... and we haven't even talked about the kernel yet!
+
+## Explicit Sync Meets Rust
+
+The previous version of the Asahi DRM kernel driver was pretty bare-bones in how it interacted with the rest of the kernel, since it had a very simple UAPI. I only had to add Rust abstractions for these DRM APIs:
+
+* `drv` and `device`, the core of DRM drivers and handling devices.
+* `file`, which is how DRM drivers interact with userspace.
+* `gem`, which manages memory for GPUs with unified memory.
+* `mm`, a generic memory range allocator which my driver uses for several things.
+* `ioctl`, just some wrappers to calculate DRM ioctl numbers for the UAPI.
+
+To add proper explicit sync support, I had to add a bunch of new abstractions!
+
+* `dma_fence`, the core Linux DMA fence mechanism.
+* `syncobj`, DRM's sync object API.
+* `sched`, which is the DRM component in charge of actually queuing GPU work and scheduling it.
+* `xarray`, a generic kernel data structure that is basically an `int` → `void *` mapping, which I use to keep track of userspace UAPI objects like VMs and queues by their unique ID.
+
+I've now [sent out](https://lore.kernel.org/asahi/687b54e7-b9a6-f37b-e5e6-8972e3670cc1@asahilina.net/T/#t) all the DRM abstractions for initial review, so we can get them upstream as soon as possible and, after that, upstream the driver itself!
+
+As part of this work, I even found two memory safety bugs in the DRM scheduler component that were causing kernel oopses for Alyssa and other developers, so the Rust driver work also benefits other kernel drivers that use this shared code! Meanwhile, I still haven't gotten any reports of kernel oopses due to bugs in the Rust code at all~ ✨
+
+## Even more stuff!
+
+Explicit sync is the biggest change for this release, but there's even more! Since we want to get the UAPI as close as possible to the final version, I've been working on adding lots more stuff:
+
+* Multiple GPU VMs (virtual memory address spaces) and GEM object binding based on the Xe UAPI model, to support future Vulkan requirements.
+* A result buffer, so the kernel driver can send GPU job execution results back to Mesa. This includes things like statistics and timings, but also whether the command succeeded and detailed fault information, so you can get verbose fault decoding right in Mesa!
+* Compute job support, to run compute shaders. We're still working on the Mesa side of this, but it should be enough to pass most tests and eventually add OpenCL support with [Rusticl](https://www.phoronix.com/news/Rusticl-OpenCL-3.0-Conformance)!
+* The ability to submit multiple GPU jobs at once, and specify their dependencies directly, without using sync objects. This allows the GPU firmware to autonomously execute everything, which is a lot more efficient than going through the DRM scheduler every time. The Gallium driver doesn't use this yet, but it probably will in the future, and our upcoming Vulkan driver definitely will! There are [a lot of subtleties](/docs/SW-AGX-driver-notes#queues) around how all the queuing stuff works...
+* Stub support for blit commands. We don't know how these work yet, but at least we have some skeleton support in the UAPI.
+
+To make all this work on the driver side, I ended up refactoring the [workqueue](https://github.com/AsahiLinux/linux/blob/gpu/rust-wip/drivers/gpu/drm/asahi/workqueue.rs) code and adding a whole new [queue](https://github.com/AsahiLinux/linux/tree/gpu/rust-wip/drivers/gpu/drm/asahi/queue) module which adds all the infrastructure to use sync objects to track command dependencies and completions and manage work via the DRM scheduler. Phew!
+
+## Conclusions
+
+So what does this all mean for users of the Asahi Linux reference distro today? It means... things are way faster!
+
+Since the Mesa driver no longer serializes GPU and CPU work, performance has improved a ton. Now we can run Xonotic at over 800 FPS, which is faster than macOS on the same hardware (M2 MacBook Air) at around 600\*! This proves that open source reverse engineered GPU drivers really have the power to beat Apple's drivers in real-world scenarios!
+
+Not only that, our driver passes 100% of the dEQP-GLES2 and dEQP-EGL conformance tests, which is better OpenGL conformance than macOS for that version. But we're not stopping there of course, with full GLES 3.0 and 3.1 support well underway thanks to Alyssa's tireless efforts! You can follow the driver's feature support progress over at the [Mesa Matrix](https://mesamatrix.net/). There have been many, many other improvements over the past few months, and we hope you find things working better and more smoothly across the board!
+
+Of course, there are lots of new corner cases we can hit now that we have support for implicit sync with an explicit sync driver. We already know of at least one minor regression (brief magenta squares for a couple of frames when KDE starts up), and there's probably more, so please report any issues on [the GitHub tracker bug](https://github.com/AsahiLinux/linux/issues/72)! The more issue reports we get, especially if they come with easy ways to reproduce the problem, the easier it is for us to debug these problems and fix them ^^.
+
+\* *Please don't take the exact number **too** seriously, as there are other differences too (Xonotic runs under Rosetta on macOS, but it was also rendering at a lower resolution there due to being a non-Retina app). The point is that the results are in the same league, and we will only keep improving our driver going forward!*
+
+## Get it!
+
+If you're already using the GPU drivers, just update your system and reboot to get the new version! Keep in mind that since the UAPI changed (a lot), apps will probably stop launching or will launch with software rendering until you reboot.
+
+If you still haven't tried the new drivers, just install the packages:
+
+```
+$ sudo pacman -Syu
+$ sudo pacman -S linux-asahi-edge mesa-asahi-edge
+$ sudo update-grub
+```
+
+Then if you're using KDE, make sure you have the Wayland session installed too:
+
+```
+$ sudo pacman -S plasma-wayland-session
+```
+
+After that, just reboot and make sure to choose a Wayland session on the login window! Remember that if you are switching from Xorg you will probably have to re-configure your display scale in the KDE settings, since KDE will think you've switched monitors. 150% is usually a good choice for laptops, and don't forget to log out and back in for the changes to fully take effect!
+
+## What's next?
+
+With the UAPI shaping up and many native ARM64 Linux games working properly... it's time to see just what we can run with the driver! OpenGL 3.x support, while not complete, is more than enough to run many games (like Darwinia and SuperTuxKart's advanced renderer). But most games are not available for ARM64 Linux so... it's time for [FEX](https://github.com/FEX-Emu/FEX)!
+
+FEX doesn't work on standard Asahi Linux kernel builds since we use 16K pages, but 4K page support is not actually that difficult to add... so starting this week, I'm going to be adding 4K support to the Asahi GPU driver and fixing whatever issues I run into along the way, and then we're going to try running Steam and Proton on it! Let's see just how much of the Steam game library we can already run with the driver in its current state! I bet you'll be surprised... (Remember Portal 2? It only requires OpenGL 2.1. With 3.x support in our driver as far as it is today, I bet we're going to have a lot of fun~ ✨)
+
+If you're interested in following my work, you can follow me at [@lina@vt.social](https://vt.social/@lina) or subscribe to my [YouTube channel](https://youtube.com/AsahiLina)! I stream my work on the Asahi GPU driver on Wednesdays and Fridays, so feel free to drop by my streams if you're interested!
+
+If you want to support my work, you can donate to marcan's Asahi Linux support fund on [GitHub Sponsors](http://github.com/sponsors/marcan) or [Patreon](https://patreon.com/marcan), which helps me out too! And if you're looking forward to a Vulkan driver, check out Ella's [GitHub Sponsors](https://github.com/sponsors/Ella-0) page! Alyssa doesn't take donations herself, but she'd love it if you donate to a charity like the [Software Freedom Conservancy](https://sfconservancy.org/) instead. (Although maybe one day I'll convince her to let me buy her an M2... ^^;;)
diff --git a/content/blog/2023/06/06-opengl-3.1.md b/content/blog/2023/06/06-opengl-3.1.md
new file mode 100644
index 0000000..8e3b4af
--- /dev/null
+++ b/content/blog/2023/06/06-opengl-3.1.md
@@ -0,0 +1,264 @@
++++
+date = "2023-06-06T22:00:00+09:00"
+draft = false
+title = "OpenGL 3.1 on Asahi Linux"
+slug = "opengl-3-1-on-asahi-linux"
+author = "Alyssa Rosenzweig"
++++
+
+Upgrade your [Asahi Linux](https://asahilinux.org/) systems, because your
+graphics drivers are getting a big boost: leapfrogging from OpenGL 2.1 over
+OpenGL 3.0 up to OpenGL 3.1! Similarly, the OpenGL ES 2.0 support is bumping up
+to OpenGL ES 3.0. That means more playable games and more functioning
+applications.
+
+Back in December, I teased an early screenshot of SuperTuxKart's deferred
+renderer working on Asahi, using OpenGL ES 3.0 features like multiple render
+targets and instancing. Now you too can enjoy SuperTuxKart with advanced
+lighting the way it's meant to be:
+
+{{< captioned caption="SuperTuxKart rendering with advanced light" >}}
+
+{{< /captioned >}}
+
+As before, these drivers are experimental and not yet conformant to the OpenGL
+or OpenGL ES specifications. For now, you'll need to run our `-edge` packages
+to opt-in to the work-in-progress drivers, understanding that there may be
+bugs. Please refer to [our previous
+post](https://asahilinux.org/2022/12/gpu-drivers-now-in-asahi-linux/)
+explaining how to install the drivers and how to report bugs to help us
+improve.
+
+With that disclaimer out of the way, there's a LOT of new functionality packed
+into OpenGL 3.0, 3.1, and OpenGL ES 3.0 to make this release. Highlights
+include:
+
+* Multiple render targets
+* Multisampling
+* [Transform feedback](https://cgit.freedesktop.org/mesa/mesa/commit/?id=d72e1418ce4f66c42f20779f50f40091d3d310b0)
+* [Texture buffer objects](https://social.treehouse.systems/@alyssa/109542058314148170)
+* ..and more.
+
+For now, let's talk about...
+
+## Multisampling
+
+Vulkan and OpenGL support _multisampling_, short for _multisampled
+anti-aliasing_. In graphics, _aliasing_ causes jagged diagonal edges due to
+rendering at insufficient resolution. One solution to aliasing is rendering at
+higher resolutions and scaling down. Edges will be blurred, not jagged, which
+looks better. Multisampling is an efficient implementation of that idea.
+
+A _multisampled_ image contains multiple _samples_ for every pixel. After
+rendering, a multisampled image is _resolved_ to a regular image with one
+sample per pixel, typically by averaging the samples within a pixel.
+
+Apple GPUs support multisampled images and framebuffers. There's quite a bit of
+typing to plumb the programmer's view of multisampling into the form understood
+by the hardware, but there's no fundamental incompatibility.
+
+The trouble comes with _sample shading_. Recall that in modern graphics, the
+colour of each _fragment_ is determined by running a _fragment shader_ given by
+the programmer. If the fragments are pixels, then each sample within that pixel
+gets the same colour. Running the fragment shader once per pixel still benefits
+from multisampling thanks to higher quality rasterization, but it's not as good
+as *actually* rendering at a higher resolution. If instead the fragments are
+samples, each sample gets a unique colour, equivalent to rendering at a higher
+resolution (supersampling). In Vulkan and OpenGL, fragment shaders generally
+run per-pixel, but with "sample shading", the application can force the
+fragment shader to run per-sample.
+
+How does sample shading work from the drivers' perspective? On a typical GPU,
+it is simple: the driver compiles a fragment shader that calculates the colour
+of a single sample, and sets a hardware bit to execute it per-sample instead of
+per-pixel. There is only one bit of state associated with sample shading. The
+hardware will execute the fragment shader multiple times per pixel, writing out
+pixel colours independently.
+
+Easy, right?
+
+Alas, Apple's "AGX" GPU is not typical.
+
+AGX always executes the shader once per pixel, not once per sample, like older
+GPUs that did not support sample shading. AGX _does_ support it, though.
+
+How? The AGX instruction set allows pixel shaders to output different colours
+to each sample. The instruction used to output a colour[^1] takes a _set_ of samples to
+modify, encoded as a bit mask. The default all-1's mask writes the same value
+to all samples in a pixel, but a mask setting a single bit will write only the
+single corresponding sample.
+
+This design is unusual, and it requires driver backflips to translate "fragment
+shaders" into hardware pixel shaders. How do we do it?
+
+Physically, the hardware executes our shader once per pixel. Logically, we're
+supposed to execute the application's fragment shader once per sample. If we
+know the number of samples per pixel, then we can wrap the application's shader
+in a loop over each sample. So, if the original fragment shader is:
+
+```
+interpolated colour = interpolate at current sample(input colour);
+output current sample(interpolated colour);
+```
+
+then we will transform the program to the pixel shader:
+
+```
+for (sample = 0; sample < number of samples; ++sample) {
+ sample mask = (1 << sample);
+ interpolated colour = interpolate at sample(input colour, sample);
+ output samples(sample mask, interpolated colour);
+}
+```
+
+The original fragment shader runs inside the loop, once per sample. Whenever it
+interpolates inputs at the current sample position, we change it to instead
+interpolate at a specific sample given by the loop counter `sample`. Likewise,
+when it outputs a colour for a sample, we change it to output the colour to the
+single sample given by the loop counter.
+
+If the story ended here, this mechanism would be silly. Adding
+sample masks to the instruction set is more complicated than a single bit to
+invoke the shader multiple times, as other GPUs do. Even Apple's own Metal
+driver has to implement this dance, because Metal has a similar approach to
+sample shading as OpenGL and Vulkan. With all this extra complexity, is there a
+benefit?
+
+If we generated that loop at the end, maybe not. But if we know at compile-time
+that sample shading is used, we can run our full optimizer on this sample loop.
+If there is an expression that is the same for all samples in a pixel, it can
+be hoisted out of the loop.[^3] Instead of
+calculating the same value multiple times, as other GPUs do, the value can be
+calculated just once and reused for each sample. Although it complicates the
+driver, this approach to sample shading isn't Apple cutting corners. If we
+slapped on the loop at the end and did no optimizations, the resulting code
+would be comparable to what other GPUs execute in hardware. There might be
+slight differences from spawning fewer threads but executing more control flow
+instructions[^2], but that's minor. Generating the loop early and running the optimizer
+enables better performance than possible on other GPUs.
+
+So is the mechanism only an optimization? Did Apple stumble on a better
+approach to sample shading that other GPUs should adopt? I wouldn't be so sure.
+
+Let's pull the curtain back. AGX has its roots as a _mobile_ GPU intended for
+iPhones, with significant PowerVR heritage. Even if it powers Mac Pros today,
+the mobile legacy means AGX prefers software implementations of many features
+that desktop GPUs implement with dedicated hardware.
+
+Yes, I'm talking about blending.
+
+Blending is an operation in graphics APIs to combine the fragment shader
+output colour with the existing colour in the framebuffer. It is usually used
+to implement [alpha blending](https://en.wikipedia.org/wiki/Alpha_compositing),
+to let the background poke through translucent objects.
+
+When multisampling is used _without_ sample shading, although the fragment
+shader only runs once per pixel, blending happens per-sample. Even if the
+fragment shader outputs the same colour to each sample, if the framebuffer
+already had different colours in different samples, blending needs to happen
+per-sample to avoid losing that information already in the framebuffer.
+
+A traditional desktop GPU blends with dedicated hardware. In the
+mobile space, there's a mix of dedicated hardware and software. On AGX,
+blending is purely software. Rather than configure blending hardware, the
+driver must produce _variants_ of the fragment shader that include
+instructions to implement the desired blend mode. With alpha
+blending, a fragment shader like:
+
+```
+colour = calculate lighting();
+output(colour);
+```
+
+becomes:
+
+```
+colour = calculate lighting();
+dest = load destination colour;
+alpha = colour.alpha;
+blended = (alpha * colour) + ((1 - alpha) * dest));
+output(blended);
+```
+
+Where's the problem?
+
+Blending happens per sample. Even if the application intends to run
+the fragment shader per pixel, the shader _must_ run per sample for
+correct blending. Compared to other GPUs, this approach to blending would
+regress performance when blending and multisampling are enabled but sample
+shading is not.
+
+On the other hand, exposing multisample pixel shaders to the driver solves the
+problem neatly. If both the blending and the multisample state are known, we
+can first insert instructions for blending, and then wrap with the sample loop.
+The above program would then become:
+
+```
+for (sample = 0; sample < number of samples; ++sample_id) {
+ colour = calculate lighting();
+
+ dest = load destination colour at sample (sample);
+ alpha = colour.alpha;
+ blended = (alpha * colour) + ((1 - alpha) * dest);
+
+ sample mask = (1 << sample);
+ output samples(sample_mask, blended);
+}
+```
+
+In this form, the fragment shader is asymptotically worse than the application
+wanted: the fragment shader is executed inside the loop, running per-sample
+unnecessarily.
+
+Have no fear, the optimizer is here. Since `colour` is the same for each sample
+in the pixel, it does not depend on the sample ID. The compiler can move the
+entire original fragment shader (and related expressions) out of the per-sample
+loop:
+
+```
+colour = calculate lighting();
+alpha = colour.alpha;
+inv_alpha = 1 - alpha;
+colour_alpha = alpha * colour;
+
+for (sample = 0; sample < number of samples; ++sample_id) {
+ dest = load destination colour at sample (sample);
+ blended = colour_alpha + (inv_alpha * dest);
+
+ sample mask = (1 << sample);
+ output samples(sample_mask, blended);
+}
+```
+
+Now blending happens per sample but the application's fragment shader runs just
+once, matching the performance characteristics of traditional GPUs. Even
+better, all of this happens without any special work from the compiler. There's
+no magic multisampling optimization happening here: it's just a loop.
+
+By the way, what do we do if we _don't_ know the blending and multisample state
+at compile-time? Hope is not lost...
+
+...but that's a story for another day.
+
+## What's next?
+
+While OpenGL ES 3.0 is an improvement over ES 2.0, we're not done. In my
+work-in-progress branch, OpenGL ES 3.1 support is nearly finished, which will
+unlock compute shaders.
+
+The final goal is a Vulkan driver running modern games. We're a while away, but
+the baseline Vulkan 1.0 requirements parallel OpenGL ES 3.1, so our work
+translates to Vulkan. For example, the multisampling compiler passes described
+above are common code between the drivers. We've tested them against OpenGL,
+and now they're ready to go for Vulkan.
+
+And yes, [the team](https://github.com/ella-0) is already working on Vulkan.
+
+Until then, you're one `pacman -Syu` away from enjoying OpenGL 3.1!
+
+[^1]: Store a formatted value to local memory acting as a tilebuffer.
+[^2]: Since the number of samples is constant, all threads branch in the same direction so the usual "GPUs are bad at branching" advice does not apply.
+[^3]: Via [common subexpression
+elimination](https://en.wikipedia.org/wiki/Common_subexpression_elimination) if
+the [loop is unrolled](https://en.wikipedia.org/wiki/Loop_unrolling), otherwise
+via [code motion](https://en.wikipedia.org/wiki/Code_motion).
diff --git a/content/blog/2023/08/02-fedora-asahi-remix.md b/content/blog/2023/08/02-fedora-asahi-remix.md
new file mode 100644
index 0000000..aa99fea
--- /dev/null
+++ b/content/blog/2023/08/02-fedora-asahi-remix.md
@@ -0,0 +1,51 @@
++++
+date = "2023-08-02T23:30:00+09:00"
+draft = false
+title = "Our new flagship distro: Fedora Asahi Remix"
+slug = "fedora-asahi-remix"
+author = "marcan"
++++
+
+You've all been waiting for it, many of you have guessed, and now, as announced at [Flock To Fedora](https://flocktofedora.org/), it's time to make it official:
+
+**The new Asahi Linux flagship distribution will be Fedora Asahi Remix!**
+
+We're confident that this new flagship will get us much closer to our goal of a polished Linux experience on Apple Silicon, and we hope you will enjoy using it as much as we're enjoying working on it.
+
+We're still working out the kinks and making things even better, so we are not quite ready to call this a release yet. We aim to officially release the Fedora Asahi Remix **by the end of August 2023**. Look forward to many new features, machine support, and more!
+
+## In the Beginning
+
+From the start of the Asahi Linux project, our goal has been to bring full Linux support to Apple Silicon machines, across all distributions. Supporting new hardware like this, especially hardware this special in the relatively young embedded ARM64 desktop Linux space is no easy task, and involves a huge amount of reverse engineering, development, and integration work, spanning all the way from bootloaders to desktop audio servers!
+
+Much of our initial work focused on the kernel and bootloaders, which can be shared between distros. But as we started reaching the point where kernel support was enough for a (bare-bones) usable system, we still had a lot of distro integration work left. Making hardware work out of the box requires a bunch of subtle integration engineering, as well as working together with userspace-level projects to improve them and add the features we need for these systems.
+
+Our goal is for all distros to eventually integrate all this work, so that users can use their choice of distro and be confident that it will work well on their machine. But, in order to kick off this process, we had to prototype what this integration looks like, which meant we had to create our own distro.
+
+And so, the Asahi Linux Arch Linux ARM remix was born. We took Arch Linux ARM, added our own [overlay package repository](https://github.com/AsahiLinux/PKGBUILDs), and packaged all of our integration work there. Notably, this is a fully downstream project: we have no significant involvement with upstream Arch Linux ARM or Arch Linux, and we directly use the Arch Linux ARM package repositories for the core distro. Our overlay just adds integration scripts, bootloader components, extra userspace support packages (for things like audio), and our forked kernel and Mesa packages.
+
+This worked well to bring Asahi Linux out into the world and the hands of eager users, but it was but a step along the way to our ultimate goal. After all, maintaining bespoke downstream distro remixes is a chore, and we can't rely on unofficial third-party support to bring our work to every other distro. We've always had our sights on deeper cooperation with upstream distros to bring Apple Silicon support directly to them as an officially supported platform, and the Arch ARM integration was mainly intended to serve as a reference for this.
+
+It didn't take long for some people to come knocking on our door...
+
+## Fedora Reaches Out
+
+Very soon after Asahi Linux started (well before our Arch ARM-based release), [Neal Gompa](https://fedoraproject.org/wiki/User:Ngompa) joined our IRC channels and we started talking about working towards integrating our work into Fedora. This was the very first offer to officially collaborate with a major upstream distro, and we were very excited! The Fedora Asahi project started in late 2021, and work began in 2022 alongside the Arch ARM release.
+
+Over the following year, we worked closely with the Fedora folks to fully integrate Apple Silicon support into Fedora, including all our custom packages, kernel and mesa forks, and special image packaging requirements, and now we're finally on the final stretch before release.
+
+## Upstream-First
+
+The Fedora Asahi effort is upstream-first, just like all of our kernel and Mesa work. Our bespoke tools, like the [m1n1](https://packages.fedoraproject.org/pkgs/m1n1/m1n1/) low-level bootloader and our [asahi-scripts](https://packages.fedoraproject.org/pkgs/asahi-scripts/asahi-scripts/) tools, are already in upstream Fedora repositories and available directly to all Fedora users (though they won't do much if you install them on a non-Apple machine!). Meanwhile, our hardware enablement package forks are kept in [COPRs](https://copr.fedorainfracloud.org/groups/g/asahi/coprs/) maintained by the [Fedora Asahi SIG](https://fedoraproject.org/wiki/SIGs/Asahi), built and served from Fedora infra.
+
+Collaborating with distro integration experts and using distro infra like this frees us up to continue focusing on what we do best: reverse engineer hardware and develop bespoke drivers and software. But not only that, it also means we can offer an even better experience for Linux on Apple Silicon users!
+
+Working directly with upstream means not only can we integrate more closely with the core distribution, but we can also get issues in other packages fixed quickly and smoothly. This is particularly important for platforms like desktop ARM64, where we still run into random app and package bugs quite often. ARM64 desktop Linux has been a niche platform (until now!), and with much less testing comes a higher propensity for bugs, so it's very important that we can address these issues quickly. Fedora already has a very solid, fully supported ARM64 port with a large userbase in the server/headless segment, so it is an excellent base to build upon and help improve the state of desktop Linux on ARM64 for everyone.
+
+We're very happy to have this level of collaboration with Fedora, and the Fedora folks have been an absolutely amazing team throughout this whole effort. We want to thank Davide Cavalca, Eric Curtin, Leif Liddy, Neal Gompa, and Michel Lind for kicking off the Asahi SIG and making this all possible.
+
+## Racing to the Finish Line
+
+We still have a lot of work to do, including integrating even more packages for new hardware support and more. Adventurous users can [try out the Fedora Asahi Remix today](https://fedora-asahi-remix.org/), but please expect rough spots (or even complete breakage). We're still very much in the process of integrating everything and a bunch of new features are coming, and things are expected to break while we get everything in shape. Please keep that in mind if you choose to try it ahead of time. We ask that reporters and bloggers wait for the official release before evaluating our work.
+
+We hope you enjoy our efforts when the time for our first official Fedora Asahi Remix release comes. You may be wondering what new features are coming, but we'll have to keep that a secret until release time (stuff isn't even integrated yet, you're not going to get a sneak peek even if you install early). Until then, please hang tight and look forward to the release!
diff --git a/content/blog/2023/08/22-first-conformant-m1-gpu-driver.md b/content/blog/2023/08/22-first-conformant-m1-gpu-driver.md
new file mode 100644
index 0000000..f80a9f4
--- /dev/null
+++ b/content/blog/2023/08/22-first-conformant-m1-gpu-driver.md
@@ -0,0 +1,215 @@
++++
+date = "2023-08-22T23:30:00+09:00"
+draft = false
+title = "The first conformant M1 GPU driver"
+slug = "first-conformant-m1-gpu-driver"
+author = "Alyssa Rosenzweig"
++++
+
+Conformant OpenGL® ES 3.1 drivers are now available for M1- and M2-family GPUs.
+That means the drivers are compatible with any OpenGL ES 3.1 application.
+Interested? [Just install Linux!](https://fedora-asahi-remix.org/)
+
+For existing [Asahi Linux](https://asahilinux.org/) users,
+upgrade your system with dnf
+upgrade (Fedora) or pacman -Syu
+(Arch) for the latest drivers.
+
+Our reverse-engineered, free and [open source graphics
+drivers](https://gitlab.freedesktop.org/asahi/mesa) are the world's ***only***
+conformant OpenGL ES 3.1 implementation for M1- and M2-family graphics
+hardware. That means our driver passed tens of thousands of tests to
+demonstrate correctness and is now recognized by the industry.
+
+To become conformant, an "implementation" must pass the official conformance
+test suite, designed to verify every feature in the specification. The test
+results are submitted to Khronos, the standards body. After a [30-day review
+period](https://www.khronos.org/conformance/adopters/), if no issues are found,
+the implementation becomes conformant. The Khronos website lists all conformant
+implementations, including our drivers for the
+[M1](https://www.khronos.org/conformance/adopters/conformant-products/opengles#submission_1007),
+[M1
+Pro/Max/Ultra](https://www.khronos.org/conformance/adopters/conformant-products/opengles#submission_1014),
+[M2](https://www.khronos.org/conformance/adopters/conformant-products/opengles#submission_1016),
+and [M2
+Pro/Max](https://www.khronos.org/conformance/adopters/conformant-products/opengles#submission_1017).
+
+Today's milestone isn't just about OpenGL ES. We're releasing the first
+conformant implementation of *any* graphics standard for the M1. And we don't
+plan to stop here ;-)
+
+[](/img/blog/2023/08/vkinstancing.webp)
+
+Unlike ours, the manufacturer's M1 drivers are unfortunately not conformant for _any_
+standard graphics API, whether Vulkan or OpenGL or OpenGL ES. That means that
+there is no guarantee that applications using the standards will work on your M1/M2 (if you're
+not running Linux). This isn't just a theoretical issue. Consider Vulkan.
+The third-party [MoltenVK](https://github.com/KhronosGroup/MoltenVK)
+layers a subset of Vulkan on top of the proprietary drivers. However, those drivers
+lack key functionality, breaking valid Vulkan applications. That hinders
+developers and users alike, if they haven't yet switched their M1/M2 computers
+to Linux.
+
+Why did *we* pursue standards conformance when the manufacturer did not? Above
+all, our commitment to quality. We want our users to know that they can depend
+on our Linux drivers. We want standard software to run without M1-specific
+hacks or porting. We want to set the right example for the ecosystem: the way forward is
+implementing open standards, conformant to the specifications, without
+compromises for "portability". We are not satisfied with proprietary
+drivers, proprietary APIs, and refusal to implement standards. The rest of the
+industry knows that progress comes from cross-vendor collaboration. We know it,
+too. Achieving conformance is a win for our community, for open source, and for
+open graphics.
+
+Of course, [Asahi Lina](https://vt.social/@lina/) and I are two individuals
+with minimal funding. It's a little awkward that we beat the big corporation...
+
+It's not too late though. They should follow our lead!
+
+---
+
+OpenGL ES 3.1 updates the experimental [OpenGL ES 3.0 and OpenGL
+3.1](/img/blog/2024/02/blog/opengl3-on-asahi-linux.html) we shipped in
+June. Notably, ES 3.1 adds compute shaders, typically used to accelerate
+general computations within graphics applications. For example, a 3D game could
+run its physics simulations in a compute shader. The simulation results can
+then be used for rendering, eliminating stalls that would otherwise be required
+to synchronize the GPU with a CPU physics simulation. That lets the game run
+faster.
+
+Let's zoom in on one new feature: atomics on images. Older versions of
+OpenGL ES allowed an application to read an image in order to display it on screen.
+ES 3.1 allows the application to *write* to the image, typically from a
+compute shader. This new feature enables flexible image processing algorithms, which
+previously needed to fit into the fixed-function 3D pipeline. However, GPUs
+are massively parallel, running thousands of threads at the same time. If two
+threads write to the same location, there is a conflict: depending which thread
+runs first, the result will be different. We have a race condition.
+
+"Atomic" access to memory provides a solution to race conditions. With atomics,
+special hardware in the memory subsystem guarantees consistent, well-defined
+results for select operations, regardless of the order of the threads. Modern
+graphics hardware supports various atomic operations, like addition,
+serving as building blocks to complex parallel algorithms.
+
+Can we put these two features together to write to an image atomically?
+
+Yes. A ubiquitous OpenGL ES
+[extension](https://registry.khronos.org/OpenGL/extensions/OES/OES_shader_image_atomic.txt),
+required for ES 3.2, adds atomics operating on pixels in an image. For
+example, a compute shader could atomically increment the value at pixel (10,
+20).
+
+Other GPUs have dedicated instructions to perform atomics on an images, making
+the driver implementation straightforward. For us, the story is more
+complicated. The M1 lacks hardware instructions for image atomics, even though
+it has non-image atomics and non-atomic images. We need to reframe the
+problem.
+
+The idea is simple: to perform an atomic on a pixel, we instead calculate
+the address of the pixel in memory and perform a regular atomic on that
+address. Since the hardware supports regular atomics, our task is "just"
+calculating the pixel's address.
+
+If the image were laid out linearly in memory, this would be straightforward:
+multiply the Y-coordinate by the number of bytes per row ("stride"), multiply
+the X-coordinate by the number of bytes per pixel, and add. That gives the
+pixel's offset in bytes relative to the first pixel of the image. To get the
+final address, we add that offset to the address of the first pixel.
+
+
+
+Alas, images are rarely linear in memory. To improve cache
+efficiency, modern graphics hardware interleaves the X- and Y-coordinates.
+Instead of one row after the next, pixels in memory follow a [spiral-like
+curve](https://fgiesen.wordpress.com/2011/01/17/texture-tiling-and-swizzling/).
+
+We need to amend our previous equation to interleave the coordinates. We could
+use many instructions to mask one bit at a time, shifting to construct the
+interleaved result, but that's inefficient. We can do better.
+
+There is a well-known ["bit twiddling" algorithm to interleave
+bits](https://graphics.stanford.edu/~seander/bithacks.html#InterleaveBMN).
+Rather than shuffle one bit at a time, the algorithm shuffles groups of bits,
+parallelizing the problem. Implementing this algorithm in shader code improves
+performance.
+
+In practice, only the lower 7-bits (or less) of each coordinate are
+interleaved. That lets us use 32-bit instructions to "vectorize" the
+interleave, by putting the X- and Y-coordinates in the low and high 16-bits of
+a 32-bit register. Those 32-bit instructions let us interleave X and Y at the
+same time, halving the instruction count. Plus, we can exploit the GPU's
+combined shift-and-add instruction. Putting the tricks together, we interleave
+in 10 instructions of M1 GPU assembly:
+
+```asm
+# Inputs x, y in r0l, r0h.
+# Output in r1.
+
+add r2, #0, r0, lsl 4
+or r1, r0, r2
+and r1, r1, #0xf0f0f0f
+add r2, #0, r1, lsl 2
+or r1, r1, r2
+and r1, r1, #0x33333333
+add r2, #0, r1, lsl 1
+or r1, r1, r2
+and r1, r1, #0x55555555
+add r1, r1l, r1h, lsl 1
+```
+
+We could stop here, but what if there's a *dedicated* instruction to interleave
+bits? PowerVR has a "shuffle" instruction
+[`shfl`](https://docs.imgtec.com/reference-manuals/powervr-instruction-set-reference/topics/bitwise-instructions/SHFL.html),
+and the M1 GPU borrows from PowerVR. Perhaps that instruction was borrowed too.
+Unfortunately, even if it was, the proprietary compiler won't use it when
+compiling our test shaders. That makes it difficult to reverse-engineer the
+instruction -- if it exists -- by observing compiled shaders.
+
+It's time to dust off a powerful reverse-engineering technique from
+magic kindergarten: guess and check.
+
+[Dougall Johnson]( https://mastodon.social/@dougall) provided the guess.
+When considering the instructions we already know about, he took special notice
+of the "reverse bits" instruction. Since reversing bits is a type of bit
+shuffle, the interleave instruction should be encoded similarly. The bit
+reverse instruction has a two-bit field specifying the operation, with value
+`01`. Related instructions to _count the number of set bits_ and _find the
+first set bit_ have values `10` and `11` respectively. That encompasses all
+known "complex bit manipulation" instructions.
+
+There is one value of the two-bit enumeration that is unobserved and unknown:
+`00`. If this interleave instruction exists, it's probably encoded like the bit
+reverse but with operation code `00` instead of `01`.
+
+There's a difficulty: the three known instructions have one single input
+source, but our instruction interleaves two sources. Where does the second
+source go? We can make a guess based on symmetry. Presumably to simplify the
+hardware decoder, M1 GPU instructions usually encode their sources
+in consistent locations across instructions. The other three instructions have
+a gap where we would expect the second source to be, in a two-source
+arithmetic instruction. Probably the second source is there.
+
+Armed with a guess, it's our turn to check. Rather than handwrite GPU assembly,
+we can hack our compiler to replace some two-source integer operation (like
+multiply) with our guessed encoding of "interleave". Then we write a compute
+shader using this operation (by "multiplying" numbers) and run it with the
+newfangled compute support in our driver.
+
+All that's left is writing a
+[shader](/img/blog/2024/02/blog/interleave.shader_test) that checks that
+the mystery instruction returns the interleaved result for each possible input.
+Since the instruction takes two 16-bit sources, there are about 4 billion
+($2^32$) inputs. With our driver, the M1 GPU manages to check them all in under
+a second, and the verdict is in: this is our interleave instruction.
+
+As for our clever vectorized assembly to interleave coordinates? We can replace
+it with one instruction. It's anticlimactic, but it's fast and it passes
+the conformance tests.
+
+And that's what matters.
+
+---
+
+_Thank you to [Khronos](https://www.khronos.org/) and [Software in the Public Interest](https://www.spi-inc.org/) for supporting open
+drivers._
diff --git a/content/blog/2024/01/11-fedora-asahi-new.md b/content/blog/2024/01/11-fedora-asahi-new.md
new file mode 100644
index 0000000..11bfb5a
--- /dev/null
+++ b/content/blog/2024/01/11-fedora-asahi-new.md
@@ -0,0 +1,200 @@
++++
+date = "2024-01-12T12:00:00+09:00"
+draft = false
+title = "New in Fedora Asahi Remix"
+slug = "fedora-asahi-new"
+author = "Eileen Yoon"
++++
+
+We're very proud to have released the first **stable** release of [Fedora Asahi Remix](/fedora) not too long ago, and now it's time to go over everything we've been up to. You may have wondered what's up with the radio silence for the past few months. The answer is that we've been busy cramming in as many features as we could into this release. We went quite a bit over our original time estimate (as they say, the last 20% of the work takes 80% of the time), but I don't see anyone complaining about new features. Here's everything new in Fedora Asahi Remix. Grab some snacks, it's long.
+
+
+## HDMI - Completing the line-up (almost!)
+
+With the Fedora Asahi Remix release, we've caught up to Apple's line-up through the M1 and M2 generations anew, including all the Pro/Max/Ultra variants. Keeping up with new chip and machine releases is a chore, and every single chip and platform needs to be explicitly brought up and supported (with all their quirks and magic numbers), but thankfully Apple tends to reuse most of the hardware logic between SoCs. Additionally, Asahi's high driver code standards focusing on code reuse and composability eases the process of bringing up new machines.
+
+But sometimes there are large changes. The reason why support for the M2-series *desktops* devices took so long is display output. To be clear: The M2 laptops released in summer of 2022 were supported after a few weeks. Display support for M2 Pro/Max laptops required not much more than adding support for the DCP firmware version used by the devices (initially 13.2/13.3 and finally 13.5). This left the M2 / M2 Pro Mac Minis and M2 Max/Ultra Mac Studios (M2+s) to support. Since iBoot no longer brings up HDMI, we need *some* Display Controller Processor (DCP) code in our bootloader [m1n1](https://github.com/AsahiLinux/m1n1) to get display on the desktops before linux loads (e.g. m1n1, u-boot, grub screen). However, unlike M1, HDMI output on M2+s is no longer managed by the DCP firmware, specifically DCP no longer handles the complete eDP -> DP2HDMI setup. In turn DCP acts more like dcpext, giving it more flexibility: for example, DCP on the M2 Mac Mini can now be routed to the USB-C/Thunderbolt ports. This makes the M2 Mac Mini Thunderbolt 4 certified. However, doing all this in our bare-metal m1n1 adds quite a bit of complexity.
+
+In addition to the existing DCP iBoot endpoint/protocol support in m1n1, two new endpoints have to be implemented: the dptx-port endpoint for AP <=> DCP eDP setup and routing and a system endpoint for verbose syslog messages. Furthermore, the (lp)dptx-phy has to be programmed based on messages exchanged via dptx-port endpoint. Finally handling all the DP configurations, which became slightly convoluted due to the lack of consistency in Apple's device tree and multi-die power management.
+
+As a minor side effect, HDMI output now works on 14-/16-inch Macbook Pros as well! (only physical HDMI ports, USB-C to HDMI cables or adapters all have a DP to HDMI converter). Our DCP driver maintainer [Janne Grunau](https://social.treehouse.systems/@janne) put in tireless work in the bootloader, device trees, and the DCP driver to [enable HDMI output](https://github.com/AsahiLinux/m1n1/pull/329). HDMI output was a TODO ever since the M1 Pro/Max series laptops. The M2+s desktop HDMI output support is based on reverse engineering and initial code by [Sven Peter](https://social.treehouse.systems/@sven). Especially the HDMI output on 14-/16-inch Macbook Pros use the existing DP phy support in atcphy. It is essentially a DP-altmode on an USB-C port without USB and USB-C controller. Large parts of this work will be reused for the upcoming Type-C DisplayPort output support, which will cover all chips including the original M1 when it is released. Note that HDMI support on M2 devices and laptops requires 13.5 firmware. The work on HDMI output is not finished: HDMI output on M2+s desktops and laptops doesn't reliably power on after s2idle (HDMI replug might fix it), resolutions/refresh rates beyond 4k 60Hz are not supported and HDMI audio support has to be finalized and tested on all devices/SoCs.
+
+{{< captioned caption="16\" M1 Max running Fedora 39 Asahi Remix with 4K HDMI monitor behind." source="Hanchin Hsieh, @yuchanns@dvd.chat" link="https://dvd.chat/notes/9mt5ifiwb2lb00ec">}}
+
+{{< /captioned >}}
+
+The only platform not yet supported is the Mac Pro, although there probably isn't much left to do. No, not the "MacBook Pro", but the "Mac Pro" -- the one that looks like a cheese grater and costs thrice as much. Few have even heard of the name. The Mac Pro is by far our least popular Mac model, and we've had much more urgent hardware enablement to do. And what about the M3, you say? Watch out for news this year...
+
+
+## GPU - Conformant OpenGL ES 3.1 & more...
+
+Over the summer of 2023, [Alyssa Rosenzweig](https://rosenzweig.io)'s GPU reverse-engineering work [leapfrogged](https://rosenzweig.io/blog/opengl3-on-asahi-linux.html) us from OpenGL 2.1 over OpenGL 3.0 up to OpenGL 3.1; similarly, the OpenGL ES 2.0 support bumped up to OpenGL ES 3.0. Just two months later, in August 2023, we shipped [conformant](https://rosenzweig.io/blog/first-conformant-m1-gpu-driver.html) OpenGL ES 3.1 drivers, the world’s only conformant OpenGL ES 3.1 implementation for M1- and M2-family graphics hardware.
+
+What's the next step? Geometry shaders are introduced in OpenGL 3.2 and OpenGL ES 3.2. A [geometry shader](https://learnopengl.com/Advanced-OpenGL/Geometry-Shader) takes as input a set of vertices that form a single primitive e.g. a point or a triangle, which then transform these vertices as it sees fit before sending them to the next shader stage. What makes the geometry shader interesting is that it is able to convert the original primitive (set of vertices) to completely different primitives, possibly generating more vertices than were initially given. In the latest Fedora release, you’ll find a newer version, OpenGL 3.3. 3.2 and 3.3 add big ticket features like geometry shaders. Since Geometry shaders are not natively supported by the Apple GPU, correctly implementing them requires driver gymnastics. This is magnified by the interactions of geometry shaders with other features like transform feedback, primitive restart, indirect draws, and tessellation. We care about correctness, a promise included with conformance. It’s paramount to implement them the correct way -- which is not the easy way.
+
+How do we implement geometry shaders without hardware support for geometry shaders? At a high level, we translate them to primitives like compute shaders, prefix sums, and indirect draws. Transform feedback is handled within the geometry-turned-compute shader. Indirect geometry draws turn into an indirect dispatch of the geometry-compute shader. Primitive restart is unrolled on the GPU with a compute prepass. Tessellation (when it is released) will feed the geometry shader as required by the spec. But is this fast? Depends. Geometry shaders are relatively slow even on desktop hardware by AMD and NVIDIA, and application developers are advised to avoid geometry shaders. Still, it’s critical that we support them correctly, because real applications use them occasionally, and we don’t want applications to be broken -- the promise of conformance. But because they are known to be [slow](http://www.joshbarczak.com/blog/?p=667) even on popular GPUs, they aren’t usually a hotspot. We just need to be fast enough. And it is.
+
+The upshot is that we now ship work in progress OpenGL 3.3, alongside the conformant OpenGL ES 3.1, which unlocks more OpenGL applications and games to work on Asahi Linux. And we’re not stopping here ;-)
+
+
+## Bluetooth - Regression fixes & M2 support
+
+After a few kernel merges, some users noticed that their Logitech Bluetooth mice were not automatically pairing anymore. While some of us accepted that such is life on Linux and started manually pairing via bluetoothctl, Janne Grunnau decided to do something about it. Following a manual git bisect of applying and testing patches one-by-one -- made possible by m1n1's hyper-fast, 10-second to desktop [kernel test cycle](/docs/Tethered-Boot-Setup-For-Developers/) -- Janne found the exact commit regressing Bluetooth Low Energy (BLE)-based pairing (used by Logitech devices) in kernel v6.4. Small low-paced Linux sub-systems are [nice](https://social.treehouse.systems/@janne/111133921649343751).
+
+Meanwhile, we also needed some tweaks for supporting Bluetooth on the new M2 Pro/Max and later machines, since they use a new Bluetooth/Wi-Fi chip. Aside from the usual [chip-specific magic numbers](https://github.com/AsahiLinux/linux/commit/9713a6347eee6d6b37aee7047b09f650bd8fc2eb), it turns out that Apple also started cryptographically signing Bluetooth firmwares - and this caused the boot process to be slower, ending up in a timeout. That took embarrassingly long to figure out, but the fix was [trivial](https://github.com/AsahiLinux/linux/commit/5dc7c9b19468e9ee618c14d9a7c0aa8dbc8a2bbf).
+
+
+## Wi-Fi - M2/M3 support & new features
+
+Apple Macs ship with Broadcom Wi-Fi hardware, but Broadcom doesn't have the closest relationship with the open source community (to put it mildly). While there is an upstream `brcmfmac` driver, it has seen minimal development over the past few years, with most maintainers inactive and receiving very few external contributions. Until now, most of our work on this driver was limited to enabling support for newer chips (which itself was quite a chore, as newer chips often brought new firmware versions and interfaces that needed to be supported). Most recently, we brought up the newer Wi-Fi chip (BCM4388) used in the latest Apple M2 (and M3) series machines. Bringup included support for cryptographically signed firmware and some newer protocols. We additionally fixed bugs to support newer Apple Wi-Fi firmware shipped with Sonoma (14.x). Along the way we also fixed Bluetooth crashing during sleep mode (Yes, the Wi-Fi driver crashing Bluetooth. Just Broadcom things..).
+
+However, just bringing up new chips does nothing to address the rest of the problems of the `brcmfmac` driver, from lack of support for newer Wi-Fi standards to weird bugs and power/throughput limitations. Thankfully, [Daniel Berlin](https://github.com/dberlin) took it upon himself to fix some of these longstanding issues and improve the Wi-Fi experience on Asahi Linux and for everyone. Wifi6 and 6E support was recently added. Throughput was also improved from around 80 Mbps max to 1200 Mbps max when connected to higher speed access points. Finally, support for low power scanning and other features significantly reduce power usage of the Wi-Fi chip.
+
+{{< captioned caption="Speed test over Wi-Fi on an M2 MacBook Air 13\"" source="https://www.speedtest.net/result/15666861184" link="https://www.speedtest.net/result/15666861184">}}
+
+{{< /captioned >}}
+
+
+## Trackpad - Correct size reporting
+
+This one's easy: We fixed a longstanding bug where every trackpad's size was reported as that of the 14" MacBook Pro. Back when trackpad support was added, we started off by just hard-coding in a single set of dimensions into the driver, and that *mostly* worked properly anyway... so nobody looked at it until now. But it does cause some subtle issues with libinput, so we finally got around to implementing support for fetching trackpad dimensions directly from the firmware. Now all trackpads, present and future, will report the right size.
+
+
+## Touchbar
+
+Apple has made some questionable input/HID decisions in the past (🦋🔑 / 🪄🐭). I'm sure all our 13-inch Macbook Pro users had some strong feelings about their function row being completely black and about as responsive as a brick. [ChaosPrincess](https://github.com/WhatAmISupposedToPutHere), of the crowd-favorite "keyboard backlight driver", returns with the Apple Z2 Touchscreen driver to light up our Macs anew, only this time in a much more sophisticated manner. While T2 machines could make the T2 itself deal with the touchbar and just emulate a regular keyboard function row, we do not have that luxury on Apple Silicon devices. In order to light up the touchbar, ChaosPrincess had to reverse engineer a touchscreen controller, a display output controller (which is a completely different display controller than the main one...), *and* write a userland daemon to drive all the hardware together. As a fun aside, those touchscreen controller and display controller are the same IP blocks as present in certain mobile iDevices, so if someone wants to use checkra1n to put full Linux on their iPhones, some of that work is now done for you ;)
+
+Our Rust userland touchbar daemon is [`tiny-dfr`](https://github.com/WhatAmISupposedToPutHere/tiny-dfr): while we obviously do not have teams of developers dedicated to the touchbar ecosystem and third-party app integration, `tiny-dfr` is equipped with the most important features: showing the F{n} row and the media control keys (brightness, volume, backlight, play, etc). And since the exact contents of those key layers are configurable, feel free to look at the config template at `/usr/share/tiny-dfr/config.toml`, all the possible settings are extensively documented there. Note that the version currently packaged in Fedora only supports the fixed key layout, but an upcoming `dnf upgrade` bringing configurability is coming very soon. Tiny, yes, but very mighty.
+
+
+## NVRAM
+
+You may have been burned by Bluetooth pairing failing after switching partitions, or you simply hate having to hold the power button down to select a non-default boot partition. How does the bootpicker make the Mac boot into a certain volume? Inside the NOR flash is a non-volatile random-access memory (NVRAM) section which stores various boot-related environment variables. When we select a volume, the bootpicker sets the NVRAM boot partition key as the selected volume, from which the Mac will source its boot options from on the next boot. The NVRAM also stores your Bluetooth pairing keys and WiFi configuration so that your input devices and networks seamlessly connect when in recovery mode! ChaosPrincess has developed a [collection of tools](https://github.com/WhatAmISupposedToPutHere/asahi-nvram/) that interact with the NVRAM chip present on Apple Silicon machines. The NVRAM tool suite (`dnf install asahi-nvram`) will be of particular interest to those who frequently switch between Linux and macOS.
+
+- `asahi-bless`: Allows you to select the default and next boot OS. "Blesses" the selected OS.
+- `asahi-btsync`: Extracts the Bluetooth pairing keys and creates bluez configs.
+- `asahi-wifisync`: Extracts the WiFi passwords and creates iwd configs.
+- `asahi-nvram`: Raw access to nvram contents. Be careful with this one. Touching some keys is a ticket to DFU City, population you.
+
+While messing with NVRAM can be dangerous and this tool suite is still in active development, `asahi-bless` is battle-tested and very safe to use, and is extremely convenient to change the boot volume of your Mac. [Davide Cavalca](https://github.com/davide125) is even working on a (WIP) GUI frontend around `asahi-bless` called [Startup Disk](https://gitlab.gnome.org/davide125/startup-disk) which gives us a pretty bootpicker interface just like macOS. Additionally, `asahi-btsync` can be quite useful to solve Bluetooth cross-OS pairing issues. In the future, we expect to have tighter NVRAM integration with the rest of the system, so that Bluetooth and Wi-Fi synchronization is performed seamlessly and in both directions, although we're not quite there yet.
+
+Again, boot and disk components should always be met with caution, but thanks to Apple Silicon's rock-solid [boot security platform design](/docs/Introduction-to-Apple-Silicon), even if you try your hardest to break your system using `asahi-nvram`, the absolute case worst that can happen is that your machine becomes unbootable and requires another machine to *reset* it (DFU) -- but you'll never irreparably, permanently *brick* it.
+
+
+## Camera
+
+To foreshadow: with good DSP, Apple can get away with shipping decades-old iPhone sensors onto the shiny-new Macs. The entire camera block (from the DisplayPort-connected CMOS sensor and the green security LED, an arm64 coprocessor, to the dedicated in-house image DSP block for filtering raw sensor output) is collectively internally called "Image Signal Processor" (ISP). That's odd, why is the entire camera block called ISP, when clearly only the last one (the DSP block) fits the "ISP" description? The name is actually pretty understandable. Not only has Apple faithfully outsourced their image sensors from Sony for a decade and ongoing, Apple has delegated much of the capture work from hardware (sensor) to software (post-processing). In other words, they cheap out on the sensor (device trees say the 720p 2020 M1 MacBook Pro is the [S5l8960x](https://theapplewiki.com/wiki/S5L8960), also known as the iPhone 5S) and rely on post-processing. The camera is really a DSP block that happens to have a sensor onboard. But I bet you didn't know that because of just how good Apple's image DSP is (Apple just can't help be good at cameras..).
+
+Moving the work from hardware to software moves the complexity to the driver. We can make use of Apple's world-class image DSP to get just as good capture output on Linux -- once we make friends with the [12MB](/docs/Introduction-to-Apple-Silicon/#firmware-overview) ISP RTOS firmware blob and tediously reverse-engineer triple-digits worth of device-specific DSP commands and the filter graphs in which they are called, that is. To keep it short, [5K+](https://github.com/AsahiLinux/linux/tree/bits/240-isp) lines of kernel code, 120 opcodes, 47 sensors (though we don't use *all* of them), 18 power domains (the worst sequencing in history), 7 interrupt channels, 2 gross buffer hacks, and 1 [teddy bear](https://vt.social/@lina/111138275387398507) later, the green LED shone to signal the camera's rolling, and now we can all go to ViCo meetings. Yay... Thanks [Eileen](https://github.com/eiln).
+
+If someone does end up porting Linux to certain handheld iDevices, and they have the luxury of caring about multimedia peripherals, the ISP driver's got you covered. Apple uses the same camera driver across the entire Apple ecosystem, so while this might just be a webcam, our driver lists compatible sensors up to the Sony IMX913 found on the iPhone 15 Max. The ISP driver should be able to drive the latest and greatest iPhone cameras with just a little extra work on your part (we've left for you dealing with strobing/flash, differentiating front/rear, and syncing multiple rear channels; hint: channel initialization takes a bitmask, the boilerplate's there).
+
+P.S. We're probably the only Linux desktop in existence to support vertical (FaceTime) video, and we uncovered some amusing userspace bugs from it. First, some apps default to the highest vertical solution, which results in unexpected behavior in case vertical video is offered. Additionally, if your webcam app has green diagonal lines through it, check the resolution: the app may have defaulted to vertical mode, and we found some apps were not respecting our driver's advertised stride of 64-bytes (which the ISP hardware operates on). The skipped data is initialized to YUV zero, which converted to RGB equals green. Feel free to report the app as per our upstream-first policy (GNOME Cheese is currently known to have issues).
+
+
+## Speakers
+
+Apple cares about audio quality. Like, they *really* care about audio quality. macOS will tell you your Mac has a single pair of stereo speakers, but in reality your Mac could have as many as six speakers, all secretly coordinated by macOS to make them seem like a single high-quality stereo pair. The 14" and 16" MacBook Pros for instance have two woofers for bass and mids and a tweeter for treble on *each* channel, an arrangement closer to a modern HiFi speaker than it is to most other laptops.
+
+Still, the laws of physics put an upper limit on how good tiny speakers can sound. Apple uses a cocktail of DSP techniques to overcome these limitations, implemented as plugins for macOS's userspace audio stack. These plugins are not compatible with Linux, so we get to either put up with terrible speaker quality, or build our own version of Apple's plugin chain. Rather than see this as a limitation, we saw an opportunity to set ourselves a lofty goal - make Apple Silicon Macs sound *better* when running Asahi Linux. We think we've succeeded.
+
+The most important thing for a loud, dynamic sound is power. Microspeakers need to be driven *very hard* in order to produce a decent sound at an acceptably loud volume. This is complicated by the fact that they are extremely delicate, and pushing even just a little bit too much power into them for even just a little bit too long is enough to permanently damage them. How do we drive these speakers hard enough to get a loud, high-quality output but not hard enough to destroy them? [speakersafetyd](https://github.com/AsahiLinux/speakersafetyd) is the world's first (and only) Free and Open Source Software implementation of a speaker protection algorithm. The amp ICs driving each speaker communicate the voltage and current going through the speaker back to the OS. speakersafetyd uses this information, as well as a few electrical and thermal parameters known about each speaker in the machine, to approximate and track each speaker's temperature. If things are getting a bit toasty, it will pull down the power until the speakers cool off. speakersafetyd and the kernel mechanisms behind it are incredibly robust, and if any part of the safety chain fails for whatever reason, the kernel will fail safe and cut all power to the speakers to prevent a meltdown.
+
+Safety? Check! Now we can start having fun. Our measurements show that the speakers in the Apple Silicon Macs bottom out at around 200 Hz. This doesn't sound right... Under macOS it seems like Apple have a full-blown subwoofer crammed into the chassis! How can this be? As it turns out, the human brain is basically mush. Your brain can be tricked into hearing frequencies that aren't really there by playing around with their harmonics, and this is exactly what Apple does to extend the bass response of a MacBook. On top of standard EQ filters to flatten out the frequency response these speakers *can* produce, [James Calligeros](https://github.com/chadmed/) wrote a bass extender called [Bankstown](https://github.com/chadmed/bankstown), which uses the same psychoacoustic tricks Apple does to get the bass pumping on Linux!
+
+Lastly, we worked with Pipewire and Wireplumber developers on a solution to automatically load our custom EQ and DSP configurations, as well as hide the "raw" output from other applications. This work was crucial, as we did not want the default desktop experience to be a fragile collection of kludges and hacks. Simply log in, and your speakers will work as they are intended to! No manual intervention required. The mechanism we designed and upstreamed is general and can be used to drive any devices with similar complex handling requirements.
+
+This is just the tip of the iceberg. A more detailed look at the journey to speaker support is in the works, so stay tuned!
+
+
+## Energy-Aware Scheduling
+
+Apple Silicon is the uncontested champion of power efficiency. It's not unusual to get 12-15 hours of battery life out of a MacBook Air on macOS. Is Apple doing some secret sauce magic to squeeze these unbelievable numbers out of the ARM64 cores? Not really. They're using tricks that Linux has been able to do for quite some time but, until now, no one has really taken advantage of.
+
+Most x86 multi-core processors are comprised of identical CPU cores copy-pasted *n*-many times - they are symmetric, and fairly distributing work to the cores is relatively simple. Apple Silicon, of course, is a heterogeneous system comprised of the performance P-cores and the efficiency E-cores. Let's try to schedule a task on Apple Silicon ourselves. We're informed that Task A requires 10 "performance" (the actual metric is unimportant). Examining our device tree, we see the performance cores can provide 10 performance at 1.2 GHz, whereas the efficiency cores can only muster that at 2.4 GHz, its maximum operating point. So the scheduler places Task A on a performance core, since it can meet the performance requirements at a lower operating point.
+
+However, we've made a critical mistake. The P-cores draw 3.7 W at 1.2 GHz whereas the E-cores actually only draw 1.6 W at 2.4 GHz (hence the name efficiency). The scheduler should have placed the task on an E-core! Energy-Aware Scheduling lets us tell the scheduler how much power each core uses at a given operating point, enabling it to make better scheduling choices that minimise energy consumption. This works a treat when the scheduler is making accurate predictions about a task's performance requirements, but what happens when it can't do that?
+
+While working on speaker support, we found that Pipewire and Wireplumber were constantly being mis-scheduled onto P-cores. By default, the kernel prioritizes never being "late" above everything else for real-time threads, thus audio processing, due to its real-time nature, was always being given full performance. We did the math, and we found we don't need anywhere near full performance to run our DSP code. To fix this, we gave Pipewire and Wireplumber the ability to use utilisation clamping, a scheduler feature that lets applications peg their performance requirements to a fixed range. We cap Pipewire and Wireplumber to an extremely low maximum performance so the scheduler restricts them to efficiency cores at their *lowest* operating point. Both still function *perfectly*, and we get to save oodles of battery life for our users! This awesome feature goes so underutilised that it wasn't even enabled in the standard Fedora kernel until we asked for it to be a couple of weeks ago (CONFIG_UCLAMP_TASK), and we sincerely hope that its enablement in Fedora leads to more widespread adoption. It's not just about reducing energy consumption, either: this feature can also be used in the other direction to optimize for performance in cases where the kernel's scheduler doesn't make good decisions by default, which can be important for games and other mixed CPU/GPU workloads.
+
+Putting EAS and utilisation clamping together, we took a 15" M2 MacBook Air from about 6 hours of useable battery life just sitting at the desktop to about 8-10 hours of 1080p30 YouTube, 12-15 hours of desktop use, and an enormous 25-28 hours of screen-off idle time. We still have many more tricks up our sleeves to eke out more battery life, and a deep dive on EAS utilisation clamping is in the works. Watch this space!
+
+
+# Userspace & Distro
+
+## `kernel-16k` - Flock to Fedora
+
+Back in the wild wild *A*-for-*Alpha* Arch Linux ARM (ALARM) days, we had two flavors of the Asahi kernel package: a baseline flavor with the necessary features enabled for Apple Silicon hardware to run Linux, and an "edge" flavor that contained the more experimental work, which some of you opted-in to be our guinea pigs by manually installing `pacman -S linux-asahi-edge`. Understandable, as the -edge package teased some irresistible offers like DCP backlight/brightness control, system-wide sleep, and GPU drivers. Fun fact, “edge” was the same git branch all along, we just disabled some riskier drivers via kernel configs. But by the end of ALARM, we pretty much advised everyone to install -edge as those drivers were mature and well-tested. In fact, Xorg+ALARM still has a bug where the cursor floats a few pixels above if you don’t have GPU drivers installed (and magically goes away once you install -edge). These edge vs. non-edge discrepancies were only causing the devs and our users pain...
+
+We took this distro migration chance (flock to fedora!) to remove `-edge` entirely. All the code that was provided through the -edge flavor has been stabilized and released into the main kernel flavor. The unified linux kernel package maintained by [Neal Gompa](https://github.com/Conan-Kudo) enables *everything* we had before under a single `kernel-16k` package, which means you get complete, high-quality hardware integration out of the box! Additionally, he has contributed the framework for the `kernel-16k` flavor to the Fedora kernel package to be enabled in the future once more of the kernel work lands upstream.
+
+Segueing from kernel to userland and distro...
+
+{{< captioned caption="Fedora 39 Asahi Remix KDE System Information">}}
+
+{{< /captioned >}}
+
+
+## Widevine - Netflix and Spotify on Asahi
+
+What good is a desktop if Netflix and Spotify doesn't work? Media distribution services often require a Digial Rights Management (DRM) system to deliver protected premium content, which goes as smoothly on FOSS Linux as you'd expect. While Apple works directly with Netflix to deploy their custom DRM solution called "FairPlay", FairPlay simply does not exist on Linux, and the hardware restricts it to only unmodified macOS installs. Still, many people need their Spotify. Widevine is Google's proprietary "cross-platform" content protection solution, so simply installing the Widevine blob should make Netflix and Spotify work. Unfortunately, one does not simply "install" Widevine on a platform that isn't officially supported by Google.
+
+Very recently, some ARM64 Linux-ish platforms with Widevine did pop into existence: some ChromeOS laptops. Unfortunately ChromeOS is only "Linux-ish", and ChromeOS binaries cannot run unmodified on standard ARM64 desktop Linux. The Widevine blobs had to be manually patched to work around both memory page alignment issues and glibc incompatibilities. Despite being a horrendous hack, we've been able to package it into a [reliable user-friendly installer](https://github.com/AsahiLinux/widevine-installer) that ships preinstalled on Fedora Asahi Remix and should work on most other ARM64 distributions with a reasonably recent glibc. The whole process can be summarized in meme format, but you can also check out [David Buchanan](https://github.com/DavidBuchanan314/)'s original write-up [here](https://www.da.vidbuchanan.co.uk/blog/netflix-on-asahi.html). Netflix and Spotify for all.
+
+{{< captioned caption="You wouldn't pay for 4K Netflix and..." source="David Buchanan, The Quest for Netflix on Asahi Linux" link="https://www.da.vidbuchanan.co.uk/blog/netflix-on-asahi.html">}}
+
+{{< /captioned >}}
+
+
+## OpenH264 - Lawyers love this one H.264 trick
+
+In tangentially related news, certain moving picture compression standards (e.g. H.264/H.265) are encumbered with vociferously defended patents, so Fedora cannot legally ship them. marcan takes pride in Asahi's seamless out-of-the-box experience, and H.264 being video people's JPEG or the "fallback codec", out-of-the-box H.264 support was imperative. Fedora does support H.264 via OpenH264 from Cisco, which is an open source H.264 implementation that is distributed as a pre-compiled binary. Cisco Systems covers the appropriate licensing royalties, as long as the binary is downloaded and installed directly from their repository. Traditionally, this means that users have had to manually install OpenH264 after installing Fedora Linux.
+
+Since our Asahi Linux installer happens to install directly from the Internet anyway, we added support for pre-downloading these codec packages directly from Cisco's servers as part of the installation process. A little script then takes care of immediately installing them on first boot, and the result is that Fedora Asahi Remix is the first Fedora spin to ship with H.264 straight out of the box, fully lawyer-approved.
+
+Users who wish to use other patent-encumbered codecs under their own resposibility may choose to install them from third-party repositories, such as the `libavcodec-freeworld` package in [RPM Fusion](https://docs.fedoraproject.org/en-US/quick-docs/rpmfusion-setup/). Note that RPM Fusion is not affiliated with Fedora nor Asahi Linux.
+
+
+# Work In Progress...
+
+Now for some tricks we have up our sleeves. These may or may not arrive sometime in 2024.
+
+
+## Hardware Video Decode
+
+OpenH264 may decode H.264 by definition, but it cannot decode H.265/HEVC, which is basically H.264 cranked up including the licensing part. OpenH264 could also be faster: it has very little SIMD code, and even less ARM64 SIMD (Janne would know..). The release of speaker support has heightened the need for fast, high-quality, and power-efficent video decoding. While software decode on the M-series cores is faster than some hardware decoders, some users report their laptop battery converts to released heat at a noticeably faster rate than macOS. We want to at least match macOS efficiency numbers.
+
+The Apple Video Decoder is a multiformat programmable hardware driven by a custom instruction set specialized for decoding video. AVD, despite its complexity, oddly enough lacks a firmware handling the low-level decode logic, so we have to RE literally every bit ourselves (side effect, the entire driver/firmware stack will be fully open-source). And video codec standards being 880-page manual beasts, it's not the easiest effort. Eileen's [avd repo](https://github.com/eiln/avd) currently boasts H.264 High Profile, High 4:2:2 Profile, High 10 Profile, and High 10 4:2:2 Profile, so that beats openh264 in features alone. HEVC is nearing conformance. A VP9 proof-of-concept exists.
+
+{{< captioned caption="AVD decoding VP9-encoded Matrix shootout scene over m1n1 proxy." source="https://github.com/eiln/avd" link="https://github.com/eiln/avd">}}
+
+{{< /captioned >}}
+
+Another hurdle is the Linux video hardware acceleration API. Current options cannot yet handle all the demands of a video decoder driver that lacks a firmware handling a signifcant chunk of the decoding logic. V4L2? VA-API? Vulkan? To be answered in 2024.
+
+
+## "Can we run Steam?"
+
+Apple Silicon devices use 16K pages, but the rest of the (x86) world runs on 4K. Running Apple Silicon on a 4K kernel is technically feasible, but it requires a number of invasive and controversial upstream changes and comes with a significant impact on performance. A better approach would be running the host with the native 16K kernel, and using a 4K kernel in a VM for those problematic workloads, assuming the performance of the VM is good enough for the use case.
+
+But 3D performance in VMs is not so good. Or is it? At [XDC 2022](https://www.youtube.com/watch?v=9sFP_yddLLQ), Rob Clark demonstrated that, with a technique called "DRM native context", it is possible to achieve near-native performance for 3D acceleration in a VM. Now the question is whether we can port DRM native context to Asahi Linux, given that it needs to be individually implemented for each DRM driver. This is a quite significant project and involves changes in multiple components. We need to implement the equivalent of Rob Clark's work on freedreno for the asahi/agx drivers both in Mesa and virglrenderer. We also need to extend libkrun (a lightweight VMM used to start and drive the VM) to support virtio-gpu+rutabaga, along with virtio-snd support, as audio tends to be quite an important feature for gaming ;-)
+
+{{< captioned caption="Portal running in a VM in Asahi at ~60 FPS." source="Sergio Lopez, @slp@fosstodon.org" link="https://fosstodon.org/@slp/111031658946870639">}}
+
+{{< /captioned >}}
+
+At the time of writing, there's an evolving MR for [virglrenderer](https://gitlab.freedesktop.org/virgl/virglrenderer/-/merge_requests/1274), and PR for [libkrun](https://github.com/containers/libkrun/pull/144) adding the necessary pieces. There's also a [blog post](https://sinrega.org/2023-10-06-using-microvms-for-gaming-on-fedora-asahi/) with instructions for giving it a try using downstream patches. [Sergio Lopez](https://fosstodon.org/@slp) hopes to have everything merged upstream and shipped ready-to-use in Fedora Asahi in the coming months.
+
+
+## DP Alt Mode & Thunderbolt
+
+> 17:30 [\](https://social.treehouse.systems/@sven): you can also mention that dp altmode and thunderbolt is in progress and should come sometime in 2024
+
+
+# Install Today!
+
+We hope you enjoyed catching up on some of the things we've been working on. Don't forget to visit our [Fedora Asahi Remix](/fedora) announcement page, and also check out our brand new [User Guide](https://docs.fedoraproject.org/en-US/fedora-asahi-remix/), which will be getting more of our user-oriented documentation going forward. See it for yourself. Install today:
+
+
+
curl https://alx.sh | sh
+
diff --git a/content/blog/2024/02/14-conformant-gl46-on-the-m1.md b/content/blog/2024/02/14-conformant-gl46-on-the-m1.md
new file mode 100644
index 0000000..fa2ac9f
--- /dev/null
+++ b/content/blog/2024/02/14-conformant-gl46-on-the-m1.md
@@ -0,0 +1,308 @@
++++
+date = "2024-02-14T12:00:00+09:00"
+draft = false
+title = "Conformant OpenGL 4.6 on the M1"
+slug = "conformant-gl46-on-the-m1"
+author = "Alyssa Rosenzweig"
++++
+
+For years, the M1 has only supported OpenGL 4.1. That changes
+today -- with our release of full OpenGL® 4.6 and OpenGL® ES 3.2!
+[Install Fedora](https://fedora-asahi-remix.org/) for the latest M1/M2-series
+drivers.
+
+Already installed? Just dnf upgrade \-\-refresh.
+
+Unlike the vendor's non-conformant 4.1 drivers, our [open
+source](https://gitlab.freedesktop.org/asahi/mesa) Linux drivers are
+**conformant** to the latest OpenGL versions, finally promising broad
+compatibility with modern OpenGL workloads, like
+[Blender](https://www.blender.org/).
+
+
+
+Conformant 4.6/3.2 drivers must pass over 100,000 tests to ensure correctness. The
+official list of conformant drivers now includes [our OpenGL
+4.6]()
+and [ES
+3.2](https://www.khronos.org/conformance/adopters/conformant-products/opengles#submission_1045).
+
+While the vendor doesn't yet support graphics standards like modern OpenGL, we do. For this Valentine's Day, we want to profess our love for
+interoperable open standards. We want to free users and developers from lock-in, enabling applications to run anywhere the heart wants without special
+ports. For that, we need standards conformance. Six months ago, we became the [first
+conformant driver for any standard graphics API for the
+M1](/blog/first-conformant-m1-gpu-driver.html) with the release of OpenGL ES
+3.1 drivers. Today, we've finished OpenGL with the full 4.6... and we're well
+on the road to Vulkan.
+
+---
+
+Compared to 4.1, OpenGL 4.6 adds dozens of required features, including:
+
+* Robustness
+* SPIR-V
+* [Clip control](/blog/asahi-gpu-part-6.html)
+* Cull distance
+* [Compute shaders](/blog/first-conformant-m1-gpu-driver.html)
+* Upgraded transform feedback
+
+Regrettably, the M1 doesn't map well to any graphics standard newer than OpenGL
+ES 3.1. While Vulkan makes some of these features optional, the missing features are
+required to layer DirectX and OpenGL on top. No existing solution on M1 gets
+past the OpenGL 4.1 feature set.
+
+How do we break the 4.1 barrier? Without hardware support, new features need
+new tricks. Geometry shaders, tessellation, and transform feedback become
+compute shaders. Cull distance becomes a transformed interpolated value. Clip
+control becomes a vertex shader epilogue. The list goes on.
+
+For a taste of the challenges we overcame, let's look at **robustness**.
+
+Built for gaming, GPUs traditionally prioritize raw performance over safety.
+Invalid application code, like a shader that reads a buffer out-of-bounds,
+can trigger undefined behaviour. Drivers exploit that to maximize performance.
+
+For applications like web browsers, that trade-off is undesirable.
+Browsers handle untrusted shaders, which they must sanitize to ensure stability
+and security. Clicking a malicious link should not crash the browser. While
+some sanitization is necessary as graphics APIs are not security barriers,
+reducing undefined behaviour in the API can assist "defence in depth".
+
+"Robustness" features can help. Without robustness, out-of-bounds buffer access
+in a shader can crash. With robustness, the application can opt for
+defined out-of-bounds behaviour, trading some performance for less attack
+surface.
+
+All modern cross-vendor APIs include robustness. Many games even
+(accidentally?) rely on robustness. Strangely, the vendor's proprietary
+API omits buffer robustness. We must do better for conformance, correctness,
+and compatibility.
+
+Let's first define the problem. Different APIs have different definitions of
+what an out-of-bounds load returns when robustness is enabled:
+
+* Zero (Direct3D, Vulkan with `robustBufferAccess2`)
+* Either zero or some data in the buffer (OpenGL, Vulkan with
+ `robustBufferAccess`)
+* Arbitrary values, but can't crash (OpenGL ES)
+
+OpenGL uses the second definition: return zero or data from the buffer.
+One approach is to return the *last* element of the buffer for
+out-of-bounds access. Given the buffer size, we can calculate the last index.
+Now consider the *minimum* of the index being accessed and the last index. That
+equals the index being accessed if it is valid, and some other valid index
+otherwise. Loading the minimum index is safe and gives a spec-compliant result.
+
+As an example, a uniform buffer load without robustness might look like:
+
+```asm
+load.i32 result, buffer, index
+```
+
+Robustness adds a single unsigned minimum (`umin`) instruction:
+
+```asm
+umin idx, index, last
+load.i32 result, buffer, idx
+```
+
+Is the robust version slower? It can be. The difference should be small
+percentage-wise, as arithmetic is faster than memory. With thousands
+of threads running in parallel, the arithmetic cost may even be hidden by the
+load's latency.
+
+There's another trick that speeds up robust uniform buffers. Like other GPUs,
+the M1 supports "preambles". The idea is simple: instead of calculating the
+same value in every thread, it's faster to calculate once and reuse the result.
+The compiler identifies eligible calculations and moves them to a preamble
+executed before the main shader. These redundancies are common, so preambles
+provide a nice speed-up.
+
+We usually move uniform buffer loads to the preamble when every thread loads
+the same index. Since the size of a uniform buffer is fixed, extra robustness
+arithmetic is *also* moved to the preamble. The robustness is "free" for the
+main shader. For robust storage buffers, the clamping might move to the
+preamble even if the load or store cannot.
+
+Armed with robust uniform and storage buffers, let's consider robust "vertex
+buffers". In graphics APIs, the application can set vertex buffers with a base
+GPU address and a chosen layout of "attributes" within each buffer. Each
+attribute has an offset and a format, and the buffer has a "stride" indicating
+the number of bytes per vertex. The vertex shader can then read attributes,
+implicitly indexing by the vertex. To do so, the shader loads the address:
+
+
+
+Some hardware implements robust vertex fetch natively. Other hardware has
+bounds-checked buffers to accelerate robust software vertex fetch.
+Unfortunately, the M1 has neither. We need to implement vertex fetch with raw
+memory loads.
+
+One instruction set feature helps. In addition to a 64-bit base address,
+the M1 GPU's memory loads also take an offset in *elements*. The hardware shifts the offset and
+adds to the 64-bit base to determine the address to
+fetch. Additionally, the M1 has a combined integer multiply-add instruction
+`imad`. Together, these features let us implement vertex loads in two
+instructions. For example, a 32-bit attribute load looks like:
+
+```asm
+imad idx, stride/4, vertex, offset/4
+load.i32 result, base, idx
+```
+
+The hardware load can perform an additional small shift. Suppose our attribute
+is a vector of 4 32-bit values, densely packed into a buffer with no offset. We can load that attribute in one instruction:
+
+```asm
+load.v4i32 result, base, vertex << 2
+```
+
+...with the hardware calculating the address:
+
+
+
+What about robustness?
+
+We want to implement robustness with a clamp, like we did for uniform
+buffers. The problem is that the vertex buffer size is given in bytes, while
+our optimized load takes an index in "vertices". A single vertex buffer can
+contain multiple attributes with different formats and offsets, so we can't
+convert the size in bytes to a size in "vertices".
+
+Let's handle the latter problem. We can rewrite the addressing equation as:
+
+
+
+That is: one buffer with many attributes at different offsets is equivalent to
+many buffers with one attribute and no offset. This gives an alternate
+perspective on the same data layout. Is this an improvement? It avoids an
+addition in the shader, at the cost of passing more data -- addresses are
+64-bit while attribute offsets are
+[16-bit](https://vulkan.gpuinfo.org/listreports.php?limit=maxVertexInputAttributeOffset&value=4294967295&platform=all0).
+More importantly, it lets us translate the vertex buffer size in bytes into a
+size in "vertices" for *each* vertex attribute. Instead of clamping the offset,
+we clamp the vertex index. We still make full use of the hardware addressing
+modes, now with robustness:
+
+```asm
+umin idx, vertex, last valid
+load.v4i32 result, base, idx << 2
+```
+
+We need to calculate the last valid vertex index ahead-of-time for each
+attribute. Each attribute has a format with a particular size. Manipulating
+the addressing equation, we can calculate the last *byte* accessed in the
+buffer (plus 1) relative to the base:
+
+
+
+The load is valid when that value is bounded by the buffer size in bytes. We
+solve the integer inequality as:
+
+
+
+The driver calculates the right-hand side and passes it into the shader.
+
+One last problem: what if a buffer is too small to load *anything*? Clamping
+won't save us -- the code would clamp to a negative index. In that case,
+the attribute is entirely invalid, so we swap the application's buffer for a
+small buffer of zeroes. Since we gave each attribute its own base address,
+this determination is per-attribute. Then clamping the index to zero
+correctly loads zeroes.
+
+Putting it together, a little driver math gives us robust buffers at the
+cost of one `umin` instruction.
+
+---
+
+In addition to buffer robustness, we need image robustness. Like its buffer
+counterpart, image robustness requires that out-of-bounds image loads return
+zero. That formalizes a guarantee that reasonable hardware already makes.
+
+...But it would be no fun if our hardware was reasonable.
+
+Running the conformance tests for image robustness, there is a single
+test failure affecting "mipmapping".
+
+For background, mipmapped images contain multiple "levels of detail". The base
+level is the original image; each successive level is the previous level
+downscaled. When rendering, the hardware selects the level closest to matching
+the on-screen size, improving efficiency and visual quality.
+
+With robustness, the specifications all agree that image loads return...
+
+* Zero if the X- or Y-coordinate is out-of-bounds
+* Zero if the level is out-of-bounds
+
+Meanwhile, image loads on the M1 GPU return...
+
+* Zero if the X- or Y-coordinate is out-of-bounds
+* Values from the last level if the level is out-of-bounds
+
+Uh-oh. Rather than returning zero for out-of-bounds levels, the hardware
+clamps the level and returns nonzero values. It's a mystery why.
+The vendor does not document their hardware publicly, forcing us to
+rely on reverse engineering to build drivers. Without documentation,
+we don't know if this behaviour is intentional or a hardware bug. Either way,
+we need a workaround to pass conformance.
+
+The obvious workaround is to never load from an invalid level:
+
+```glsl
+if (level <= levels) {
+ return imageLoad(x, y, level);
+} else {
+ return 0;
+}
+```
+
+That involves branching, which is inefficient. Loading an out-of-bounds level
+doesn't crash, so we can speculatively load and then use a compare-and-select
+operation instead of branching:
+
+```glsl
+vec4 data = imageLoad(x, y, level);
+
+return (level <= levels) ? data : 0;
+```
+
+This workaround is okay, but it could be improved. While the M1 GPU has combined
+compare-and-select instructions, the instruction set is *scalar*. Each thread
+processes one value at a time, not a vector of multiple values. However, image
+loads return a vector of four components (red, green, blue, alpha). While the
+pseudo-code looks efficient, the resulting assembly is not:
+
+```asm
+image_load R, x, y, level
+ulesel R[0], level, levels, R[0], 0
+ulesel R[1], level, levels, R[1], 0
+ulesel R[2], level, levels, R[2], 0
+ulesel R[3], level, levels, R[3], 0
+```
+
+Fortunately, the vendor driver has a trick. We know the hardware returns zero
+if either X or Y is out-of-bounds, so we can *force* a zero output by *setting*
+X or Y out-of-bounds. As the maximum image size is 16384 pixels wide, any X
+greater than 16384 is out-of-bounds. That justifies an alternate workaround:
+
+```glsl
+bool valid = (level <= levels);
+int x_ = valid ? x : 20000;
+
+return imageLoad(x_, y, level);
+```
+
+Why is this better? We only change a single scalar, not a whole vector,
+compiling to compact scalar assembly:
+
+```asm
+ulesel x_, level, levels, x, #20000
+image_load R, x_, y, level
+```
+
+If we preload the constant to a uniform register, the workaround is a single
+instruction. That's optimal -- and it passes conformance.
+
+---
+
+_Blender ["Wanderer"](https://download.blender.org/demo/eevee/wanderer/wanderer.blend) demo by [Daniel Bystedt](https://www.artstation.com/dbystedt), licensed CC BY-SA._
diff --git a/content/blog/2024/06/05-vk13-on-the-m1-in-1-month.md b/content/blog/2024/06/05-vk13-on-the-m1-in-1-month.md
new file mode 100644
index 0000000..09f970b
--- /dev/null
+++ b/content/blog/2024/06/05-vk13-on-the-m1-in-1-month.md
@@ -0,0 +1,412 @@
++++
+date = "2024-06-05T12:00:00+09:00"
+draft = false
+title = "Vulkan 1.3 on the M1 in 1 month"
+slug = "vk13-on-the-m1-in-1-month"
+author = "Alyssa Rosenzweig"
++++
+
+
+
+Finally, conformant Vulkan for the M1! The new "Honeykrisp" driver is the first
+[conformant
+Vulkan®](https://www.khronos.org/conformance/adopters/conformant-products/vulkan#submission_780)
+for Apple hardware on any operating system, implementing the full 1.3 spec
+without "portability" waivers.
+
+Honeykrisp is **not yet released** for end users. We're
+continuing to add features, improve performance, and port to more hardware.
+[Source
+code](https://gitlab.freedesktop.org/alyssa/mesa/-/tree/honeykrisp-20240506-2/src/asahi/vulkan?ref_type=heads)
+is available for developers.
+
+HoloCure running on Honeykrisp ft. DXVK, FEX, and Proton.
+
+Honeykrisp is not based on prior M1 Vulkan efforts, but rather
+[Faith Ekstrand](https://mastodon.gamedev.place/@gfxstrand)'s open source [NVK
+driver](https://www.collabora.com/news-and-blog/news-and-events/introducing-nvk.html)
+for NVIDIA GPUs. In her words:
+
+> All Vulkan drivers in Mesa trace their lineage to the Intel Vulkan
+> driver and started by copying+pasting from it. My hope is that NVK
+> will eventually become the driver that everyone copies and pastes from. To
+> that end, I'm building NVK with all the best practices we've developed for
+> Vulkan drivers over the last 7.5 years and trying to keep the code-base clean
+> and well-organized.
+
+Why spend years implementing features from scratch when we can reuse NVK?
+There will be friction starting out, given NVIDIA's desktop architecture
+differs from the M1's mobile roots. In exchange, we get a modern driver
+designed for desktop games.
+
+We'll need to pass a half-million tests ensuring correctness, [submit the
+results](https://www.khronos.org/conformance/adopters), and then we'll become
+conformant after 30 days of industry review. Starting from NVK and our OpenGL
+4.6 driver... can we write a driver passing the Vulkan 1.3 conformance test
+suite *faster* than the 30 day review period?
+
+It's unprecedented...
+
+Challenge accepted.
+
+### April 2
+
+It begins with a text.
+
+> _Faith... I think I want to write a Vulkan driver._
+
+Her advice?
+
+> _Just start typing._
+
+There's no copy-pasting yet -- we just add M1 code to NVK and
+remove NVIDIA as we go. Since the kernel mediates our access to the hardware, we
+begin connecting "NVK" to [Asahi Lina](https://vt.social/@lina)'s kernel
+driver using code shared with OpenGL. Then we plug in our shader
+compiler and hit the hay.
+
+### April 3
+
+To access resources, GPUs use "descriptors" containing the address, format, and
+size of a resource. Vulkan bundles descriptors into "sets" per the application's "descriptor
+set layout". When compiling shaders, the driver lowers descriptor accesses to
+marry the set layout with the hardware's data structures. As our descriptors
+differ from NVIDIA's, our next task is adapting NVK's descriptor set lowering.
+We start with a simple but correct approach, deleting far more code than we
+add.
+
+### April 4
+
+With working descriptors, we can compile compute shaders. Now we program
+the fixed-function hardware to dispatch compute. We first add
+bookkeeping to map Vulkan command buffers to lists of M1 "control streams",
+then we generate a compute control stream. We copy that code from our OpenGL
+driver, translate the GL into Vulkan, and compute works.
+
+That's enough to move on to "copies" of buffers and images. We implement
+Vulkan's copies with compute shaders, internally dispatched
+with Vulkan commands as if we were the application. The first copy test
+passes.
+
+### April 5
+
+Fleshing out yesterday's code, *all* copy tests pass.
+
+### April 6
+
+We're ready to tackle graphics. The novelty is handling graphics state like
+depth/stencil. That's straightforward, but there's a *lot*
+of state to handle. Faith's code collects all "dynamic state" into a single
+structure, which we translate into hardware control words. As usual, we grab
+that translation from our OpenGL driver, blend with NVK, and move on.
+
+### April 7
+
+What makes state "dynamic"? Dynamic state can change without
+recompiling shaders. By contrast, static state is baked into shader
+binaries called "pipelines". If games create all their pipelines
+during a loading screen, there is no compiler "stutter" during gameplay. The
+idea hasn't quite panned out: many game developers don't know their state
+ahead-of-time so cannot create pipelines early. In response, Vulkan has
+[made](https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_EXT_extended_dynamic_state.html)
+[ever](https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_EXT_extended_dynamic_state2.html)
+[more](https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_EXT_extended_dynamic_state3.html)
+[state](https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_EXT_vertex_input_dynamic_state.html)
+[dynamic](https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_EXT_graphics_pipeline_library.html), punctuated with the
+[`EXT_shader_object`](https://www.khronos.org/blog/you-can-use-vulkan-without-pipelines-today)
+extension that makes pipelines *optional*.
+
+We want full dynamic state and shader objects. Unfortunately, the M1 bakes
+random state into shaders: vertex attributes, fragment outputs, blending, even
+linked interpolation qualifiers. Like most of the industry in the 2010s, the
+M1's designers bet on pipelines.
+
+Faced with this hardware, a reasonable driver developer would double-down on
+pipelines. DXVK would stutter, but we'd pass conformance.
+
+I am not reasonable.
+
+To eliminate stuttering in OpenGL, we make state dynamic with four strategies:
+
+* Conditional code.
+* Precompiled variants.
+* Indirection.
+* Prologs and epilogs.
+
+Wait, what-a-logs?
+
+AMD also bakes state into shaders... with a twist. They divide the
+hardware binary into three parts: a *prolog*, the shader, and an *epilog*.
+Confining dynamic state to the periphery eliminates shader variants. They
+compile prologs and epilogs on the fly, but that's fast and doesn't stutter.
+Linking shader parts is a quick concatenation, or long jumps avoid linking
+altogether. This strategy works for the M1, too.
+
+For Honeykrisp, let's follow NVK's lead and treat _all_ state as dynamic.
+No other Vulkan driver has implemented full dynamic state and shader objects
+this early on, but it avoids refactoring later. Today we add the code to build,
+compile, and cache prologs and epilogs.
+
+Putting it together, we get a (dynamic) triangle:
+
+[](/img/blog/2024/06/hk-triangle.png)
+
+### April 8
+
+Guided by the list of failing tests, we wire up the little bits missed along
+the way, like translating border colours.
+
+```c
+/* Translate an American VkBorderColor into a Canadian agx_border_colour */
+enum agx_border_colour
+translate_border_color(VkBorderColor color)
+{
+ switch (color) {
+ case VK_BORDER_COLOR_INT_TRANSPARENT_BLACK:
+ return AGX_BORDER_COLOUR_TRANSPARENT_BLACK;
+ ...
+ }
+}
+```
+
+Test results are getting there.
+
+> **Pass**: 149770, **Fail**: 7741, **Crash**: 2396
+
+That's good enough for [vkQuake](https://github.com/Novum/vkQuake).
+
+[](/img/blog/2024/06/vkquake.png)\
+
+### April 9
+
+Lots of little fixes bring us to a 99.6% pass rate... for Vulkan 1.1. Why stop
+there? NVK is 1.3 conformant, so let's claim 1.3 and skip to the finish line.
+
+> **Pass**: 255209, **Fail**: 3818, **Crash**: 599
+
+98.3% pass rate for 1.3 on our 1 week anniversary.
+
+Not bad.
+
+### April 10
+
+SuperTuxKart has a Vulkan renderer.
+
+[](/img/blog/2024/06/hkr-stk.png)
+
+### April 11
+
+[Zink](https://docs.mesa3d.org/drivers/zink.html) works too.
+
+[](/img/blog/2024/06/hkr-stk-zink.png)
+
+### April 12
+
+I tracked down some fails to a test bug, where an arbitrary verification
+threshold was too strict to pass on some devices. I filed a bug report, and it's
+[resolved](https://github.com/KhronosGroup/VK-GL-CTS/commit/5fd73c841d775dff1ad52d8340d79dc120d64696)
+within a few weeks.
+
+### April 16
+
+The tests for "descriptor indexing" revealed a compiler bug affecting subgroup
+shuffles in non-uniform control flow. The M1's shuffle instruction is quirky,
+but it's easy to workaround. Fixing that fixes the descriptor indexing tests.
+
+### April 17
+
+A few tests crash inside our register allocator. Their shaders contain a
+peculiar construction:
+
+```c
+if (condition) {
+ while (true) { }
+}
+```
+
+`condition` is always false, but the compiler doesn't know that.
+
+Infinite loops are nominally invalid since shaders must terminate in finite
+time, but this shader is syntactically valid. "All loops contain a break" seems
+obvious for a shader, but it's false. It's straightforward to fix register
+allocation, but what a doozy.
+
+### April 18
+
+Remember copies? They're slow, and every frame currently requires a copy to get
+on screen.
+
+For "zero copy" rendering, we need enough Linux window system integration to
+negotiate an efficient surface layout across process boundaries. Linux uses
+"modifiers" for this purpose, so we implement the
+[`EXT_image_drm_format_modifier`](https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_EXT_image_drm_format_modifier.html)
+extension. And by implement, I mean copy.
+
+Copies to avoid copies.
+
+### April 20
+
+> _"I'd like a 4K x86 Windows Direct3D PC game on a 16K arm64 Linux Vulkan Mac."_
+>
+> ...
+>
+> _"Ma'am, this is a Wendy's."_
+
+### April 22
+
+As bug fixing slows down, we step back and check our driver architecture.
+Since we treat all state as dynamic, we don't pre-pack control words during
+pipeline creation. That adds theoretical CPU overhead.
+
+Is that a problem? After some optimization,
+[vkoverhead](https://github.com/zmike/vkoverhead) says we're pushing 100
+million draws per second.
+
+I think we're okay.
+
+### April 24
+
+Time to light up YCbCr. If we don't use special YCbCr hardware,
+this feature is "software-only". However, it touches a *lot* of code.
+
+It touches so much code that [Mohamed
+Ahmed](https://mohamexiety.github.io/posts/final_report/) spent an entire
+summer adding it to NVK.
+
+Which means he spent a summer adding it to Honeykrisp.
+
+Thanks, Mohamed ;-)
+
+### April 25
+
+Query copies are next. In Vulkan, the application can query the number of samples rendered,
+writing the result into an opaque
+"query pool". The result can be copied from the query pool on the CPU or GPU.
+
+For the CPU, the driver maps the pool's internal data structure and copies the
+result. This may require nontrivial repacking.
+
+For the GPU, we need to repack in a compute shader. That's harder, because
+we can't just run C code on the GPU, right?
+
+...Actually, we can.
+
+A little witchcraft makes GPU query copies as easy as C.
+
+```c
+void copy_query(struct params *p, int i) {
+ uintptr_t dst = p->dest + i * p->stride;
+ int query = p->first + i;
+
+ if (p->available[query] || p->partial) {
+ int q = p->index[query];
+ write_result(dst, p->_64, p->results[q]);
+ }
+
+ ...
+}
+```
+
+### April 26
+
+The final boss: border colours, hard mode.
+
+Direct3D lets the application choose an arbitrary border colour when
+creating a sampler. By contrast, Vulkan only requires three border colours:
+
+* **`(0, 0, 0, 0)`** -- transparent black
+* **`(0, 0, 0, 1)`** -- opaque black
+* **`(1, 1, 1, 1)`** -- opaque white
+
+We handled these on April 8. Unfortunately, there are two problems.
+
+First, we need custom border colours for Direct3D compatibility. Both [DXVK](https://github.com/doitsujin/dxvk) and
+[vkd3d-proton](https://github.com/HansKristian-Work/vkd3d-proton) require the
+[`EXT_custom_border_color`](https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_EXT_custom_border_color.html)
+extension.
+
+Second, there's a subtle problem with our hardware, causing dozens of fails
+even without custom border colours. To understand the issue, let's revisit
+texture descriptors, which contain a
+pixel _format_ and a component reordering _swizzle_.
+
+Some formats are implicitly reordered. Common "BGRA" formats swap red and blue
+for [historical
+reasons](https://stackoverflow.com/questions/74924790/why-bgra-instead-of-rgba).
+The M1 does not directly support these formats. Instead, the driver composes
+the swizzle with the format's reordering. If the application uses a `BARB`
+swizzle with a `BGRA` format, the driver uses an `RABR` swizzle with an
+`RGBA` format.
+
+There's a catch: swizzles apply to the border colour, but formats do not. We
+need to *undo* the format reordering when programming the border colour for
+correct results after the hardware applies the composed swizzle. Our OpenGL
+driver implements border colours this way, because it knows the texture format
+when creating the sampler. Unfortunately, Vulkan doesn't give us that
+information.
+
+Without custom border colour support, we "should" be okay. Swapping red
+and blue doesn't change anything if the colour is white or black.
+
+There's an even *subtler* catch. Vulkan mandates support for a
+packed 16-bit format with 4-bit components. The M1 supports a similar format...
+but with reversed "endianness", swapping red and *alpha*.
+
+That still seems okay. For transparent black (all zero) and opaque white (all
+one), swapping components doesn't change the result.
+
+The problem is opaque black: (0, 0, 0,
+1). Swapping red and alpha gives (1,
+0, 0, 0). Transparent red? Uh-oh.
+
+We're stuck. No known hardware configuration implements correct Vulkan
+semantics.
+
+Is hope lost?
+
+Do we give up?
+
+A reasonable person would.
+
+I am not reasonable.
+
+Let's jump into the deep end. If we implement custom border colours, opaque
+black becomes a special case. But how? The M1's custom border colours entangle
+the texture format with the sampler. A reasonable person would skip Direct3D
+support.
+
+As you know, I am not reasonable.
+
+Although the hardware is unsuitable, we control software. Whenever a shader
+samples a texture, we'll inject code to fix up the border colour. This
+emulation is simple, correct, and slow. We'll use dirty driver
+tricks to speed it up later. For now, we eat the cost, advertise full custom border
+colours, and pass the opaque black tests.
+
+### April 27
+
+All that's left is some last minute bug fixing, and...
+
+> **Pass**: 686930, **Fail**: 0
+
+Success.
+
+### The future
+
+The next task is implementing everything that
+[DXVK](https://github.com/doitsujin/dxvk/blob/master/VP_DXVK_requirements.json)
+and
+[vkd3d-proton](https://github.com/HansKristian-Work/vkd3d-proton/blob/master/VP_D3D12_VKD3D_PROTON_profile.json)
+require to layer Direct3D. That includes esoteric extensions like
+[transform feedback](https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_EXT_transform_feedback.html). Then [Wine](https://www.winehq.org/) and an [open source x86
+emulator](https://github.com/FEX-Emu/FEX) will run Windows games on [Asahi
+Linux](https://asahilinux.org/).
+
+That's getting ahead of ourselves. In the mean time, enjoy Linux games with
+our [conformant OpenGL
+4.6](/img/blog/2024/06/blog/conformant-gl46-on-the-m1.html) drivers... and
+stay tuned.
+
+Baby Storm running on Honeykrisp ft. DXVK, FEX, and Proton.
+
+---
diff --git a/content/blog/2024/10/10-aaa-gaming-on-m1.md b/content/blog/2024/10/10-aaa-gaming-on-m1.md
new file mode 100644
index 0000000..d50797c
--- /dev/null
+++ b/content/blog/2024/10/10-aaa-gaming-on-m1.md
@@ -0,0 +1,170 @@
++++
+date = "2024-10-10T10:00:00-04:00"
+draft = false
+title = "AAA gaming on Asahi Linux"
+slug = "aaa-gaming-on-asahi-linux"
+author = "Alyssa Rosenzweig"
++++
+
+Gaming on Linux on M1 is here! We're thrilled to release our Asahi game playing
+toolkit, which integrates our Vulkan 1.3 drivers with x86 emulation and Windows
+compatibility. Plus a bonus: conformant OpenCL 3.0.
+
+Asahi Linux now ships the only conformant [OpenGL®](https://www.khronos.org/conformance/adopters/conformant-products/opengl#submission_3470),
+[OpenCL™](https://www.khronos.org/conformance/adopters/conformant-products/opencl#submission_433), and
+[Vulkan®](https://www.khronos.org/conformance/adopters/conformant-products#submission_7910)
+drivers for this hardware. As for gaming... while today's release is an alpha, [**Control**](https://store.steampowered.com/app/870780/Control_Ultimate_Edition/) runs well!
+
+
+
+## Installation
+
+First, install [Fedora Asahi Remix](https://asahilinux.org/fedora/). Once
+installed, get the latest drivers with dnf
+upgrade \-\-refresh && reboot. Then just dnf install steam and play. While all M1/M2-series systems work, most games require 16GB of memory due to emulation overhead.
+
+## The stack
+
+Games are typically x86 Windows binaries rendering with DirectX, while our target is Arm Linux
+with Vulkan. We need to handle each difference:
+
+* [FEX](https://fex-emu.com/) emulates x86 on Arm.
+* [Wine](https://www.winehq.org/) translates Windows to Linux.
+* [DXVK](https://github.com/doitsujin/dxvk) and [vkd3d-proton](https://github.com/HansKristian-Work/vkd3d-proton) translate DirectX to Vulkan.
+
+There's one curveball: page size. Operating systems allocate memory in fixed
+size "pages". If an application expects smaller pages than the system uses,
+they will break due to insufficient alignment of allocations. That's a problem:
+x86 expects 4K pages but Apple systems use 16K pages.
+
+While Linux can't mix page sizes between processes, it *can* virtualize another
+Arm Linux kernel with a different page size. So we run games inside a tiny
+virtual machine using [muvm](https://github.com/AsahiLinux/muvm), passing through
+devices like the GPU and game controllers. The
+hardware is happy because the system is 16K, the game is happy because the
+virtual machine is 4K, and you're happy because you can play [**Fallout
+4**](https://store.steampowered.com/app/377160/Fallout_4/).
+
+
+
+## Vulkan
+
+The final piece is an adult-level Vulkan driver, since translating DirectX requires Vulkan 1.3
+with many extensions. Back in April, I wrote
+[Honeykrisp](https://rosenzweig.io/blog/vk13-on-the-m1-in-1-month.html), the
+only Vulkan 1.3 driver for Apple hardware. I've since added DXVK support. Let's look at some new features.
+
+### Tessellation
+
+Tessellation enables games like [**The Witcher 3**](https://store.steampowered.com/app/292030/The_Witcher_3_Wild_Hunt/) to generate
+geometry. The M1 has hardware tessellation, but it is
+too limited for DirectX, Vulkan, or OpenGL. We must instead tessellate with arcane compute shaders, as detailed in [today's talk at XDC2024](https://www.youtube.com/live/pDsksRBLXPk).
+
+
+
+### Geometry shaders
+
+Geometry shaders are an older, cruder method to generate geometry. Like
+tessellation, the M1 lacks geometry shader hardware so we emulate with compute.
+Is that fast? No, but geometry shaders are slow [even on desktop
+GPUs](http://www.joshbarczak.com/blog/?p=667). They don't need to be fast --
+just fast enough for games like
+[**Ghostrunner**](https://store.steampowered.com/app/1139900/Ghostrunner/).
+
+
+
+### Enhanced robustness
+
+"Robustness" permits an application's shaders to access buffers out-of-bounds
+without crashing the hardware. In OpenGL and Vulkan, out-of-bounds loads may
+return arbitrary elements, and out-of-bounds stores may corrupt the buffer.
+Our OpenGL driver [exploits this
+definition](https://rosenzweig.io/blog/conformant-gl46-on-the-m1.html) for
+efficient robustness on the M1.
+
+Some games require stronger guarantees. In DirectX, out-of-bounds loads return zero, and
+out-of-bounds stores are ignored. DXVK therefore requires
+[`VK_EXT_robustness2`](https://docs.vulkan.org/guide/latest/robustness.html#_vk_ext_robustness2),
+a Vulkan extension strengthening robustness.
+
+Like before, we implement robustness with compare-and-select instructions. A
+naïve implementation would *compare* a loaded index with the buffer size and
+*select* a zero result if out-of-bounds. However, our GPU loads are vector
+while arithmetic is scalar. Even if we disabled page faults, we would need up
+to four compare-and-selects per load.
+
+```asm
+load R, buffer, index * 16
+ulesel R[0], index, size, R[0], 0
+ulesel R[1], index, size, R[1], 0
+ulesel R[2], index, size, R[2], 0
+ulesel R[3], index, size, R[3], 0
+```
+
+There's a trick: reserve *64 gigabytes* of zeroes using virtual memory voodoo.
+Since every 32-bit index multiplied by 16 fits in 64 gigabytes, any index into
+this region loads zeroes. For out-of-bounds loads, we simply replace the buffer
+address with the reserved address while preserving the index. Replacing a
+64-bit address costs just two 32-bit compare-and-selects.
+
+```asm
+ulesel buffer.lo, index, size, buffer.lo, RESERVED.lo
+ulesel buffer.hi, index, size, buffer.hi, RESERVED.hi
+load R, buffer, index * 16
+```
+
+Two instructions, not four.
+
+## Next steps
+
+Sparse texturing is next for Honeykrisp, which will unlock more DX12 games. The alpha already runs DX12 games that don't require sparse, like [**Cyberpunk
+2077**](https://store.steampowered.com/app/1091500/Cyberpunk_2077/).
+
+
+
+While many games are playable, newer AAA titles don't hit 60fps *yet*.
+Correctness comes first. Performance improves next. Indie games like
+[**Hollow Knight**](https://store.steampowered.com/app/367520/Hollow_Knight/) do run full speed.
+
+
+
+Beyond gaming, we're adding general purpose x86 emulation based on this
+stack. For more information, [see the
+FAQ](https://docs.fedoraproject.org/en-US/fedora-asahi-remix/x86-support/).
+
+Today's alpha is a taste of what's to come. Not the final form, but
+enough to enjoy [**Portal 2**](https://store.steampowered.com/app/620/Portal_2/) while we work towards "1.0".
+
+
+
+## Acknowledgements
+
+This work has been years in the making with major contributions from...
+
+* [Alyssa Rosenzweig](https://rosenzweig.io)
+* [Asahi Lina](https://lina.yt/me)
+* [chaos_princess](https://social.treehouse.systems/@chaos_princess)
+* [Davide Cavalca](https://github.com/davide125)
+* [Dougall Johnson](https://mastodon.social/@dougall)
+* [Ella Stanforth](https://ella.gay)
+* [Faith Ekstrand](https://www.gfxstrand.net/faith/welcome/)
+* [Janne Grunau](https://social.treehouse.systems/@janne)
+* [Karol Herbst](https://chaos.social/@karolherbst)
+* [marcan](https://social.treehouse.systems/@marcan)
+* [Mary Guillemard](https://mary.zone)
+* [Neal Gompa](https://neal.gompa.dev/)
+* [Sergio López](https://sinrega.org)
+* [TellowKrinkle](https://github.com/TellowKrinkle)
+* [Teoh Han Hui](https://github.com/teohhanhui)
+* [Rob Clark](https://mastodon.gamedev.place/@robclark)
+* [Ryan Houdek](https://github.com/sonicadvance1)
+
+... Plus hundreds of developers whose work we build upon, spanning the Linux,
+Mesa, Wine, and FEX projects. Today's release is
+thanks to the magic of open source.
+
+We hope you enjoy the magic.
+
+Happy gaming.
diff --git a/content/blog/2024/12/12-muvm-updates.md b/content/blog/2024/12/12-muvm-updates.md
new file mode 100644
index 0000000..11dea76
--- /dev/null
+++ b/content/blog/2024/12/12-muvm-updates.md
@@ -0,0 +1,179 @@
++++
+date = "2024-12-12T00:00:00-00:00"
+draft = false
+title = "Beyond Gaming: X11 bridging in muvm"
+slug = "muvm-x11-bridging"
+author = "Asahi Lina"
++++
+
+Hi everyone! We've just shipped a really cool update to our x86/x86-64 emulation stack on Asahi Linux, and I wanted to share what we've been working on. As of today, non-game apps are now usable!
+
+{{< captioned caption="Cisco Packet Tracer running on Fedora Asahi Remix">}}
+
+{{< /captioned >}}
+
+## Native graphics in VMs
+
+As you might remember from our [previous blog post](https://asahilinux.org/2024/10/aaa-gaming-on-asahi-linux/), Asahi Linux runs all x86/x86-64 apps in a microVM driven by [muvm](https://github.com/AsahiLinux/muvm). How can we manage to run games in a real VM with near-native performance, without hardware GPU passthrough?
+
+On AMD/Intel systems (and, indeed, also on macOS on Apple Silicon), GPU virtualization has always been kind of limited. Your options are to either fully pass through the hardware GPU, or use API-level GPU paravirtualization. Passing through the hardware GPU fully assigns the GPU device to the guest, which means it sees it as a "real" GPU device. This works for all guest OSes that have real drivers for that GPU, and it has native performance, but it means the GPU is dedicated to the guest, so you can't share it with the host or integrate guest and host windows together on one screen. Meanwhile, API-level GPU paravirtualization essentially sends the OpenGL, Vulkan, or Metal commands from the guest to the host, so they are processed by the host's GPU driver stack. This requires "generic" paravirt GPU drivers in the guest, and it is much slower than native GPU usage because all the high-level GPU drawing commands have to cross the guest-to-host barrier and be processed on the host. This is how GPU virtualization works on macOS. Some GPUs (e.g. recent Nvidia GPUs) support true sharing with hardware virtualization support, but that isn't upstream yet and requires hardware support, which Apple GPUs don't have.
+
+But what if there was a better way? It turns out, there is! Enter [DRM Native Context](https://indico.freedesktop.org/event/2/contributions/53/attachments/76/121/XDC2022_%20virtgpu%20drm%20native%20context.pdf).
+
+The concept is quite simple: Instead of running the entire GPU driver stack on the guest and passing through the whole hardware GPU (no sharing), or running the entire GPU driver stack on the host and passing through high-level APIs (slow), why not split it down the middle? DRM Native Context runs the GPU *kernel driver* on the host, and the GPU *userspace driver* (Mesa) on the guest, and passes through the *kernel UAPI interface* from the guest to the host.
+
+This gives us the best of both worlds: Since the GPU userspace drivers run in the guest, they can run with full performance just as if they were driving a real, hardware GPU. And since the GPU kernel driver runs in the host, it can be shared between host applications and guest applications. A simplified render operation might go like this:
+
+1. The application issues GL or Vulkan draw commands to draw things on the screen. A game might perform thousands of these per frame.
+2. The userspace Mesa driver in the guest takes these commands and converts them to GPU command structures. These command structures are written *directly into GPU memory* which the driver has previously mapped directly from the host using the virtio-gpu protocol, so it's just as fast as running natively.
+3. The application flushes the draw stream or otherwise requests the GPU begin rendering.
+4. The userspace Mesa driver prepares the overall render information, the same way it would if running natively on the host.
+5. Mesa then wraps the command in a virtio-gpu *execution buffer*, which has the information needed to pass through the command to the host.
+6. The command, which is only a kilobyte or two of data at most, travels via the guest kernel virtio-gpu driver into the host virtual machine monitor.
+7. The VMM receives the command and passes it on to [virglrenderer](https://gitlab.freedesktop.org/asahi/virglrenderer), which unwraps the native UAPI GPU command structure.
+8. virglrenderer issues the `ioctl()` to pass through the command to the host GPU kernel driver.
+9. The host GPU kernel driver sends the command to the GPU.
+
+The process to render natively on the host is exactly the same, except it removes steps 5 through 7 (in step 8, Mesa would issue the `ioctl()` directly). Therefore, the overhead is quite small, since the extra guest-to-host communication only involves a tiny amount of data, instead of having to pass through entire GL or Vulkan command streams. It also means we can run the same exact drivers as we would natively, so we know the GPU features should be exactly the same, with the same GPU driver quality and compatibility.
+
+What about security and isolation? Each process on the guest is handled as an independent GPU process from the point of view of the host kernel driver (more specifically, each time a guest process opens the virtual GPU device node, the host VMM opens the real GPU device node for it as a separate file descriptor). This means that guest GPU processes are isolated just as native GPU processes are from each other.
+
+As of today, DRM native context is only upstream for [freedreno](https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14900), so you've probably never heard of it if you're used to x86 machines! However, PRs are in flight for [Intel](https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/29870) and [AMD](https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21658) GPUs, and I think this really is the future of GPU virtualization for Linux guests on Linux hosts (and perhaps, some day, Windows guests running Mesa on Windows)!
+
+We shipped DRM native context with our gaming update in October, and the results speak for themselves.
+
+So where's the catch? As you might expect, performance isn't *quite* native. The performance impact comes from *synchronization*: Sending commands to the GPU takes a little bit longer, and waiting for GPU commands to complete takes a little bit longer. Applications that "fire-and-forget" lots of GPU work all at once will see nearly native performance, while applications that wait for GPU work to complete often will suffer increased latency and lower throughput. Applications that use multiple GPU queues and synchronize between them will also suffer today, as that synchronization happens through the VM guest, but we plan to improve this by moving GPU-to-GPU synchronization to the host kernel just as it would happen for native apps (we just haven't implemented this yet).
+
+But just getting GPU rendering to work in the guest is only half the story...
+
+## Window systems attack
+
+While DRM native context by itself lets the guest render on the GPU, we haven't talked about display yet! It would be possible to use a virtual screen device like a traditional VM and have the guest show up as a whole separate desktop in a window, but that's not what we want for our stack. We want the VM to be a thin layer, and applications to show up natively on the host window system.
+
+Crosvm, the ChromeOS VMM that muvm and libkrun's graphics support shares code with, does this using a feature called *cross-domain contexts*. virtio-gpu lets the guest open a communications channel, which the host VMM can then forward to a host compositor. Crosvm uses this to implement [Wayland forwarding](https://crosvm.dev/book/devices/wayland.html) using a guest Wayland compositor called *sommelier*. sommelier listens on the Wayland socket on the guest, and forwards the requests to the host Wayland compositor. Forwarding just the protocol isn't enough (otherwise you could do this using virtio vsock or TCP or anything else): sommelier needs to also extract buffer file descriptors that are passed through as part of the Wayland command stream, and use virtio-gpu mechanisms to *directly* share them between the host and the guest. This allows window framebuffers to be shared, so they can be composited on the host without any extra copying cost. On the host VMM side, this is handled by the cross-domain component of [rutabaga_gfx](https://github.com/containers/libkrun/tree/v1.9.5/src/rutabaga_gfx/src/cross_domain), which implements the commands to forward the Wayland protocol and convert shared buffers back to fds that the host Wayland compositor can understand.
+
+There was one extra catch: Synchronization. When a GPU app on the guest renders to a buffer, it passes it directly to the host before waiting for the rendering to finish. A mechanism called *implicit sync* is supposed to let the kernel handle synchronization directly: The kernel knows what GPU operations are pending on the buffer and makes the GPU wait until they complete before reading from it in another context. Implicit sync is considered a legacy feature, so our GPU kernel driver does not implement it, but instead we implement it in Mesa for compatibility (Nvidia refused to do this, and this is why Wayland was broken on Nvidia GPUs for so long...). Our Mesa driver inserts implicit sync information (*GPU fences*) into shared buffers automatically when they are a render target, and extracts the fences on the other end before reading from the buffer. This worked great on both the host and guest, but did not work on buffers shared between the host and the guest: When guest Mesa inserted a fence in the guest buffer, that fence was only registered in the guest kernel, so the host kernel had no idea about the ongoing render and couldn't hand back the fence to the host Mesa when needed. This caused tearing, visual glitches, and "frame lag". To fix this, I ended up just going back to implicit sync for now: The Asahi virtgpu protocol now includes a buffer list with submissions just like "classic" implicit sync drivers, and those buffers have fences registered for them in the host VMM, in virglrenderer code. The implicit sync compatibility code runs twice, once in the guest Mesa and once in the host VMM, to cover all the bases. In the future, we do plan to implement explicit sync properly, integrate it with the cross-domain stuff, and remove this hack, but that will have to wait a bit, since it needs non-upstreamed guest kernel patches... but I digress.
+
+What about X11? Most games need X11 to run, so sommelier can run its own *XWayland* instance in the guest to provide X11 support. Easy, right?
+
+We shipped this solution in October and... it didn't go so well.
+
+## Sommelier woes
+
+As it turns out, sommelier isn't quite as nice a solution as we'd hoped. It is designed to be used in a ChromeOS host, and it doesn't work quite as well on more general Linux desktops.
+
+sommelier both does *too much* and *too little*. It is quite a complicated piece of code, doing lots of Wayland protocol parsing, buffer copying, and more. This means that applications on the guest don't quite act as applications running natively on the host. There were lots of problems with things like DPI scaling and window/popup placement. At the same time, sommelier doesn't do enough to integrate with XWayland. On popular Wayland desktop environments like KDE Plasma, the compositor does a lot of extra work to integrate with X11 applications properly, talking directly to XWayland to manage them. None of this works with sommelier, which provides only bare-bones X11 integration. X11 apps are missing title bars, menus don't work properly, the clipboard doesn't work properly, there is no system tray integration, some windows showed up weirdly transparent...
+
+On top of that, sommelier is written in C and doesn't fully isolate client connections. It generally works well enough with an XWayland client, but oddities can cause it to crash and bring down the whole VM environment. Native Wayland proxying was out of the question: We tried it and it was too broken to be usable at all.
+
+So, we decided to ship with sommelier and XWayland as an X11-only solution (no Wayland socket support), and advertise it as a game-only solution, since full-screen apps generally worked well enough. This meant running Steam in Big Picture mode (since windowed mode was quite broken). It also meant that games that used windowed launchers often weren't usable.
+
+But we needed a better solution.
+
+## X11 first?
+
+Back before muvm was even called muvm, I had experimented with direct X11 forwarding over virtio vsock sockets. This works much like running X11 over the network or an SSH tunnel. The disadvantage of this is that it can't work with GPU acceleration, since there is no way to pass through GPU buffers over a "dumb" socket like this. Still, running some apps while forcing software rendering, it was clear that this was a much better solution for non-game apps. X11 apps worked exactly as they did on the host, with no window management issues, properly working clipboard and tray integration, etc.. I was prepared to ship this is an alternative for non-game apps as-is, but I wondered how hard it would be to get GPU acceleration working... and then [chaos_princess](https://social.treehouse.systems/@chaos_princess) showed up with something they called *x112virtgpu*.
+
+{{< sidenote >}}
+Why the focus on X11, when Wayland is the future? Quite simply, because most x86/x86-64 apps people want to run are not built for or predate Wayland support. While we are all-in on Wayland for native desktop environments running on Asahi Linux, XWayland is still fully supported, and for games and legacy applications running under emulation, prioritizing X11 protocol support is the smart thing to do. The solution we shipped in October never supported Wayland applications despite using Wayland under the hood (we tried to enable it and it was really broken), so switching to an X11-only solution for now is not a regression.
+{{< /sidenote >}}
+
+x112virtgpu, now renamed to *muvm-x11bridge*, is exactly what we would have wanted sommelier to be: A thin proxy for the X11 protocol, which uses a cross-domain channel to forward directly to the host X server while passing through framebuffers without any copying, using virtgpu buffer sharing. Unlike sommelier, it doesn't try to interpret the X11 protocol more than is necessary to extract commands that need special handling. This means that it works just as well as direct X11 passthrough does, plus GPU acceleration and buffer sharing.
+
+... or that's the theory anyway. There was one teeeeeny catch...
+
+## Futex what?
+
+The X11 protocol is quite *peculiar*. Besides passing through framebuffers using file descriptors, it also passes through something else: *fences*. No, not modern GPU explicit sync fences (those are supported too in X11 as of very recently, but that's another story). CPU-side fences, which are implemented using... futexes.
+
+Whaaa?
+
+[Futex](https://en.wikipedia.org/wiki/Futex) is a kernel system call for doing cross-thread and cross-process synchronization on Linux. It's basically a build-your-own mutex primitive. The two threads or processes are supposed to *share memory directly*, and synchronize using atomics. When one process needs to wait for another, it uses the kernel `futex()` system call to put itself to sleep, and when another process needs to wake it up, it uses the same system call to do so. The kernel makes sure the system calls are synchronized with the actual value of the shared memory, so there are no race conditions.
+
+We need to make this work between host and guests processes... but there's no such thing as a cross-domain `futex()` system call. The host and guest kernel have no idea about each others' futexes. And to make this work at all, we need to share the memory...
+
+We *could* solve this problem at a high level, interpreting the X11 protocol more to understand exactly what futex fences are used for. Each side, host VMM and x11bridge, would have to understand which side is responsible for signaling and waiting on a futex. Then, the proxy components on the signaling end would have to wait for the signal, then send a cross-domain command to forward that signal to the other end. This would *work*, but it would both be a lot of *work*, and add extra latency: The futex mechanism is supposed to work without any system calls at all if one side isn't waiting on the other, by using atomic operations directly.
+
+So chaos_princess decided to try something else: What if we could actually share memory? If the host and guest processes could actually map a shared memory buffer together, then they could use atomics just as if they were both running on the same side, and then we'd only have to proxy the `futex()` system call usage somehow. This turned out to be viable, but how can we share memory? We could use GPU buffers, but that seems a bit excessive, and not really possible to integrate directly with the X server and clients...
+
+The library in charge of handling X11 shared-memory fences is *libxshmfence*. This library can use multiple mechanisms to share memory. On Linux, it [defaults to `memfd()`](https://gitlab.freedesktop.org/xorg/lib/libxshmfence/-/blob/libxshmfence-1.3.2/src/xshmfence_alloc.c?ref_type=tags#L78), which is a system call that creates "in-memory" files. Can we share those across the VM boundary? Unfortunately, not easily.
+
+But there is another way.
+
+In muvm, we already share the host filesystem directly to the guest. This is essentially a *FUSE* filesystem proxied across to the VM. Normally, this works by copying data around when reading and writing files. However, there is a special mode, called *virtiofs DAX*, which allows the guest to directly map host files into memory! When a filesystem is shared and mounted with DAX, a `mmap()` in the host and in the guest of the same file will *actually share memory directly*, and atomic operations will work between the guest and the host! How cool is that?
+
+As it turns out, DAX is kind of new and slightly broken, and I ended up having to send several patches to both libkrun and the guest kernel to get it to work reliably (we're still figuring out how to upstream some of those...). But once it worked, it meant that we could directly share memory between the guest and the host. muvm now does this by mounting `/dev/shm` in the guest with DAX support, so the host and the guest can share POSIX shared memory.
+
+But... libxshmfence still insists on using memfds. How do we fix this?
+
+chaos_princess, true to their name, decided to go full chaos mode with their solution: *ptrace*! When muvm-x11bridge gets a memfd from a client process, it *ptraces it and injects the necessary system calls to open a /dev/shm file and swap out the file descriptors as if nothing happened*. Then the filename can just be passed to the host, where libkrun can open it and hand the fd to the X server as if nothing happened.
+
+Then, muvm-x11bridge runs a little futex watcher thread, which detects `futex()` wakeup calls from the client process and sends wakeups to the host, which can forward them to the X server.
+
+Madness! But it worked... kind of? It took quite a while to debug this whole setup, since the `ptrace()` dance was very finicky and it took several tries to make it work well, and the `futex()` proxying also turned out to be quite hard to get right. We did get it to work quite reliably in the end, but there is a significant limitation: You can't use ptrace for other purposes with X11 client apps, since it will break `muvm-x11bridge`. This means you can't use *strace* to debug things, and some complicated apps that like to use ptrace (like Chromium and Chromium-based apps) would run into trouble.
+
+One possible alternative would be to use `LD_PRELOAD` to hijack libxshmfence, and this is another solution that chaos_princess implemented... but since we're also doing this whole thing across 3 architectures (native arm64, emulated x86, and emulated x86-64), we'd have to ship three versions of the library, and this solution is also not guaranteed to work properly with container technologies.
+
+We needed a better solution if we seriously wanted to ship this...
+
+## Futexes, take 2
+
+Looking closely at the libxshmfence code, it turns out there are [several fallback paths](https://gitlab.freedesktop.org/xorg/lib/libxshmfence/-/blob/libxshmfence-1.3.2/src/xshmfence_alloc.c?ref_type=tags#L82) if `memfd()` does not work. First, it uses `shm_open(SHM_ANON, ...)`, but that's a BSD thing and not available on Linux. Then, it tries `open()` with `O_TMPFILE`, but `O_TMPFILE` is not supported by virtiofs. Finally, it does it the old-school way, by opening a file in `/dev/shm` and unlinking it. If we could get it to just not use `memfd()`, it would do exactly what we want. Can we?
+
+I tried several things, including using a [seccomp-bpf](https://www.kernel.org/doc/html/v5.1/userspace-api/seccomp_filter.html) filter to disable the `memfd()` system call. Unfortunately, that breaks stuff like some codepaths in FEX, which assume `memfd()` exists and is working (which is a pretty reasonable assumption on any modern Linux kernel).
+
+Sooo... I ended up just sending a little [merge request](https://gitlab.freedesktop.org/xorg/lib/libxshmfence/-/merge_requests/9) to libxshmfence to allow disabling `memfd()` usage using an environment variable... and it was merged!
+
+This patch is not released as a new libxshmfence version yet, so any distributions that want to ship the new muvm version will have to backport this patch to their libxshmfence packages at this time, to avoid falling back on the less-reliable `ptrace()` hack.
+
+{{< sidenote >}}
+Thankfully, these fences are always *created* on the X11 client and shared *to* the X server, so only the X11 client in the guest needs the hacks, and the X server can use libxshmfence without any extra environment variables or patches.
+{{< /sidenote >}}
+
+We're done, right? Not quite... libxshmfence still deletes the shared memory file and passes only the fd to the X11 server. That's desirable (it avoids risking leaving stale files around in error cases), and we don't want to introduce more hacks into libxshmfence... so how do we pass the fd to the host side if we can't reopen the file?
+
+Well... if you think about it, even if the file is deleted, every fd open in the guest *is* actually opened by the host VMM. That's how virtiofs works! So the host *already* has the file descriptor we need somewhere... we just need to find it. To make this work, I ended up adding a magic fd-export `ioctl()` to the virtiofs implementation in libkrun. This works sort-of like exporting GPU buffers and gives you an identifier that you can pass to the host as part of the X11 cross-domain protocol, which can then reference a special table of *exported file descriptors* to locate the underlying host fd. This is implemented by sharing the exported-fd table between the virtiofs code and the rutabaga_gfx cross-domain code, which is quite a few layers of code to plumb it through... but Sergio was happy enough with this solution and [merged my PR](https://github.com/containers/libkrun/pull/231) \^\^.
+
+{{< sidenote >}}
+This trick isn't secure in the sense that multiple *independent* cross-domain clients, possibly running as different users, could steal each other's FDs, but we only have one instance of muvm-x11bridge anyway and the entire microVM runs in the context of a single user's permissions, so this doesn't affect our use case. Besides, I don't think virtgpu cross-domain has any meaningful permission checks today anyway.
+{{< /sidenote >}}
+
+Finally, after a lot more debugging of the futex and cross-domain X11 code, it was finally stable and ready to merge and release!
+
+## What about Wayland?
+
+In the future, we'd also like to support native Wayland passthrough. To do this, we'll need a Wayland counterpart to muvm-x11bridge. Unlike sommelier, this is planned to be much simpler and follow the same philosophy, and we expect it to work as well as X11 passthrough. However, we should probably get the fencing and explicit sync stuff worked out first, so pure Wayland passthrough will remain on the to-do list... for now. The good news is it doesn't have any weird futex stuff!
+
+## Muvm, reloaded
+
+If you update your Fedora Asahi Remix system today with `sudo dnf update --refresh`, you'll get all these improvements to our x86 emulation stack over the October release:
+
+### muvm changes
+- `muvm-x11bridge` for direct X11 passthrough (you can use `--sommelier` to revert back to sommelier, but why would you?).
+ * Steam and other windowed apps now work properly, and even the system tray icon works.
+ * You can also use CJK input methods in Steam using good old XIM, if they are configured properly on the host! (Tested with fcitx on KDE Plasma.)
+- `muvm-hidpipe` is now integrated, so gamepads will work without using our `steam` wrapper. In fact, after Steam is installed once, you can run it with `muvm -- FEXBash -c '~/.local/share/Steam/steam.sh'` without any loss of functionality.
+- `/dev/shm` is now shared between the host and the guest, enabling interesting use cases.
+- Guest memory is now better managed, which should lead to fewer host OOMs.
+- 8GB machines default to a higher memory allocation, which makes more games playable on those.
+- Interactive mode to run commands within an already-running VM. For example, run `muvm -ti -- bash` to get a shell.
+- You can also run commands as root by connecting to the root-server port: `muvm -tip 3335 -- bash`.
+- Lots of little improvements and fixes.
+
+### FEX changes
+- Many [bugfixes and improvements](https://fex-emu.com/FEX-2412/), including fixes for the new Steam CEF update.
+
+### virglrenderer & Mesa changes
+- [Vulkan 1.4 support](https://social.treehouse.systems/@AsahiLinux/113584784231664115)
+- Many bugfixes and performance improvements
+
+### steam wrapper changes
+- Steam now starts in regular windowed mode, instead of Big Picture mode.
+
+{{< captioned caption="Steam with the standard windowed UI, with working Japanese input">}}
+
+{{< /captioned >}}
+
+We have also automated the installation of all the required bits and pieces to run non-Steam applications, so you don't need our `steam` package if you don't want to run Steam. Just update your system first as above, then `sudo dnf install fex-emu` to get everything you need to run x86 and x86-64 applications with `muvm`.
+
+Now that window management works reasonably well, we encourage you to try non-game apps. In general, applications packaged as stand-alone tarballs (without complex OS dependencies or interaction with other applications) are likely to work well, including AppImages. Note that Flatpak does not integrate with FEX/muvm, so x86-64 Flatpaks will not work yet. Let us know how well it works for you!
diff --git a/content/blog/2025/02/12-passing-the-torch.md b/content/blog/2025/02/12-passing-the-torch.md
new file mode 100644
index 0000000..938c0f5
--- /dev/null
+++ b/content/blog/2025/02/12-passing-the-torch.md
@@ -0,0 +1,89 @@
++++
+date = "2025-02-13T14:00:00-00:00"
+draft = false
+title = "Passing the torch on Asahi Linux"
+slug = "passing-the-torch"
+author = "The Asahi Linux team"
++++
+
+With a heavy heart, we announce the resignation of Asahi Linux founder Hector
+Martin (marcan). His statement is on [his
+blog](https://marcan.st/2025/02/resigning-as-asahi-linux-project-lead/). Asahi
+Linux brings Linux to Apple Silicon, supporting audio, webcams, graphics
+acceleration, and more. As the remaining developers, we are taking this as an
+opportunity to build sustainable project governance. No matter how talented an
+individual, a large project cannot rest on a single person's shoulders. So
+instead of one replacement... we have seven:
+
+* [**Alyssa Rosenzweig**](https://rosenzweig.io), graphics dev.
+* [**chaos_princess**](https://social.treehouse.systems/@chaos_princess), kernel dev.
+* [**Davide Cavalca**](https://github.com/davide125), Fedora dev.
+* [**Neal Gompa**](https://royalgeekworld.com/), Fedora dev.
+* [**James Calligeros**](https://social.treehouse.systems/@chadmed), audio dev.
+* [**Janne Grunau**](https://social.treehouse.systems/@janne), kernel dev.
+* [**Sven Peter**](https://social.treehouse.systems/@sven), kernel dev.
+
+When it comes to project decision-making, we will share equal power in
+accordance with our [new governance](/governance). Nobody's contributions last
+forever. These governance changes will allow the project to persist as
+developers come and go.
+
+Asahi Linux relies primarily on volunteer contributors. Although some
+contributors have individual Patreon or GitHub Sponsors accounts, individual
+funding streams cannot sustain a team. Going forward, our new fiscal sponsor
+Open Source Collective will instead facilitate donations to the project as a
+whole.
+
+Our [Open Collective](https://opencollective.com/asahilinux) therefore replaces
+marcan's Patreon as the primary funding source for the project. The Patreon
+will wind down soon. Four years ago, your Patreon support made this project
+possible. As his Patreon is winding down, today we ask for your support to make
+the project possible for years to come. Your support will allow us to purchase
+hardware and fund developer time. Please consider joining us on [Open
+Collective](https://opencollective.com/asahilinux) to continue supporting
+the project.
+
+What can you look forward to in 2025?
+
+Our priority is kernel upstreaming. Our downstream Linux tree contains over
+1000 patches required for Apple Silicon that are not yet in upstream Linux. The
+upstream kernel moves fast, requiring us to constantly rebase our changes on
+top of upstream while battling merge conflicts and regressions. Janne, Neal,
+and marcan have rebased our tree for years, but it is laborious with so many
+patches. Before adding more, we need to reduce our patch stack to remain
+sustainable long-term. We cannot predict how the process will go, but we are
+committed to do our part.
+
+The other sustainability issue is testing. We must ensure that every supported
+feature works on all supported hardware, with no regressions over time. As we
+support more features and hardware, the testing requirements explode.
+Unfortunately, manual testing is time-intensive, and bugs *still* slip through.
+The solution is continuous integration (CI) that automatically tests Asahi
+Linux on many devices. Like upstreaming, building this infrastructure is not
+glamorous, but it will protect the project's long-term health.
+
+Where do the M3 and M4 fit in? Until upstreaming and CI progress, the core team
+cannot prioritize new hardware. Nevertheless, some community members are busy
+reverse-engineering to prepare for when the foundations are solid.
+
+Of course, there *are* new features coming for M1 and M2 devices. In 2025, we
+expect to release...
+
+* **DP alt mode**, required for external monitors over USB-C on laptops without a physical HDMI port.
+* **Sparse images** in our [Vulkan driver](/2024/06/vk13-on-the-m1-in-1-month/), enabling DirectX 12. In the mean
+ time, you can [enjoy DirectX 11 games](/2024/10/aaa-gaming-on-asahi-linux/) on Asahi Linux.
+* **Internal microphones**. External mics already work via the 3.5mm jack, and internal mics are coming soon.
+
+How soon? On select laptops -- just a few days! Microphone support is made
+possible by a collaboration between James, chaos_princess, and [Eileen
+Yoon](https://github.com/eiln/). On Apple Silicon, the microphones require
+kernel support for multiple hardware blocks, including the Always-On Processor
+(AOP) and the Secure Enclave (SEP), as well as userspace support for
+[beamforming](https://en.wikipedia.org/wiki/Beamforming) to make sure the audio
+sounds great. It's not just samples-in, samples-out... but those three were up
+to the challenge.
+
+Today's news is bittersweet. We are grateful to marcan for kicking off this
+project and tirelessly working on it these past years. Our community will miss
+him. Still, with your support, the project has a bright future to come.
diff --git a/content/blog/2025/03/21-progress-report-6-14.md b/content/blog/2025/03/21-progress-report-6-14.md
new file mode 100644
index 0000000..4eae8e9
--- /dev/null
+++ b/content/blog/2025/03/21-progress-report-6-14.md
@@ -0,0 +1,252 @@
++++
+date = "2025-03-21T09:00:00+10:00"
+draft = false
+title = "Progress Report: Linux 6.14"
+slug = "progress-report-6-14"
+author = "James Calligeros"
++++
+
+As March draws to a close and Linux 6.14 nears release, now is a good time to
+provide you all with our first major progress update since [taking the lead on
+the project](https://asahilinux.org/2025/02/passing-the-torch/). Going forward,
+we hope to keep these updates in sync with upstream kernel releases. We feel
+that this is a natural cadence given the focus on upstreaming, with enough time
+between posts for noteworthy downstream changes to accumulate.
+
+After getting through all the administrative work required to keep the lights
+on after marcan's departure, we've hit the ground running with upstream patch
+submission. We held our first board meeting under interesting circumstances,
+and we've even managed to sneak a couple of new features in downstream
+while you weren't looking. So, without further ado, let's get into it.
+
+## Our first board meeting
+We held our inaugural board meeting on 7 March, under challenging conditions
+for some. Neal and Davide battled crappy conference hall WiFi while at Southern
+California Linux Expo, while I sat in the dark with no power as Tropical Cyclone
+Alfred ravaged Southeast Queensland and northern New South Wales. Despite this,
+we managed to get through quite a bit. You can find the meeting minutes
+[here](https://asahilinux.org/docs/project/board/minutes/20250307).
+
+## Lightening the load
+After four years of development, we have racked up a considerable patch
+set. Here are some quick-fire stats:
+
+- 90,000+ lines of code added to the Linux kernel as of 6.13, across 1250 patches
+- A downstream U-Boot with a number of Apple Silicon and USB stack fixes
+- A downstream Mesa - required since our GPU uAPI is not upstream yet
+- A downstream virglrenderer - required since our GPU uAPI is not upstream yet
+- A downstream Flatpak runtime extension - required since we have a downstream Mesa
+
+This is... less than ideal. Rebasing, testing, and releasing
+our forks is a massive drain on our time. This is especially true
+of Janne, who has the Sisyphean task of keeping our kernel patch set applying
+upstream and porting it to every stable point release. That is hours of work
+on an almost weekly basis, especially as the pace of Rust abstraction upstreaming
+increases. We can't keep doing this.
+
+We want to bring you M3 and M4 support. We want to bring you Thunderbolt. We want
+to bring you DisplayPort Alt Mode. We want to bring you Variable Refresh Rate, and
+HDR, and hardware accelerated video playback, and better power management for the
+Pro/Max/Ultra Macs. To do that, however, we must start reducing the amount of patches
+we're carrying downstream. Most of what we're carrying is stable and has been
+for years. So after a month of tireless effort, how are we doing?
+
+We have submitted three new drivers upstream - the Image Signal Processor (ISP)
+driver, which is necessary for webcam support, and drivers for the Touchbar's
+display controller and input digitiser. These three drivers total to almost
+8,000 lines of code, with the ISP driver being 6,000 of those. The good news is
+that both Touchbar drivers have already been accepted! Thanks to chaos_princess
+for taking on the responsibility of preparing and submitting all three.
+
+Alyssa and Janne have been hard at work tidying up the GPU driver to prepare it for
+submission. This has involved some changes to the uAPI, which should slightly
+improve performance for some workloads.
+
+Now that Rust for Linux abstractions are starting to be merged at a healthy
+pace, we are faced with an emerging challenge. It is rare for
+any kernel patch to survive the mailing list without at least a couple of
+non-trivial changes, and Rust abstractions are no exception. Every time an
+abstraction used by our driver is merged, we must drop our downstream version
+and rebase the driver atop the version accepted upstream. This is gruelling, menial,
+and unpleasant work, and Janne has our deepest gratitude for volunteering his
+time to get through it.
+
+We have also been working to clean up and upstream other parts of the kernel.
+In addition to a number of miscellaneous fixes and changes for drivers already
+upstreamed such as the NVMe and I2C controllers, we have also submitted
+changes to the upstream Texas Instruments TAS2764 and TAS2770 speaker amplifier
+drivers which extend them to support the Apple-specific variants found in
+Apple Silicon Macs. Through this process, we found that the ASoC maintainers
+had already been cherry-picking some commits from our development branches!
+
+We're far from done, but we are committed to getting through this vital work.
+More patches are being submitted all the time, so watch this space!
+
+## Is this thing on?
+By the time you're reading this, we will have enabled microphone support on
+most laptops! This has been a long time coming, with Martin Povišer, Eileen
+Yoon, and chaos_princess having reverse engineered and developed a driver
+for the Always-On Processor (AOP) in Rust quite some time ago. This is Apple
+though. Nothing is ever simple.
+
+Before even getting to play with the mics in Linux, we hit a hurdle.
+On certain machines, the Secure Enclave is in the path of the physical mic
+data lines. If SEP is unhappy, you don't get mic access. chaos_princess
+quickly reverse engineered the SEP endpoint responsible, and wrote a
+stub driver to simply toggle the hardware mic switch on. With data now
+coming in to ALSA on all machines, we can continue.
+
+In all laptops released so far, Apple use three Pulse Density Modulation
+(PDM) mics wired up to an ADC and decimator in the AOP. All three mics are
+plumbed directly to userspace on separate channels, with no preamplification.
+Having three mics enables Apple to use beamforming, which is a signal processing
+technique to greatly enhance the directivity and sensitivity of an array of sensors.
+Originally developed for RADAR and military communications, it's now mostly known
+for being a marketing dot point for WiFi access points. It's also really, really,
+really hard.
+
+Unfortunately, PDM mics are very omnidirectional and very sensitive. We cannot
+get by without some kind of beamforming. I initially tried
+a very basic delay-and-sum beamformer, which involves no advanced signal
+processing. However since the mics are only about 2cm apart and only sample at
+48 kHz, we cannot achieve the temporal resolution required to make this
+approach work. Signal processing it is, then.
+
+The mysteries of signal processing in the acoustic domain are truly understood by
+very few. After consulting the scant available literature on the matter and my high
+school maths textbooks, I thought I had absolutely no hope of doing a good job of this.
+I put out a call for help on Mastodon, however no one offered to step up. Fine, I'll
+do it myself.
+
+After reading a few more papers, I found an approach that looked familiar to me.
+A Minimum Variance Distortionless Response beamformer works by taking your complex
+sample data in the time domain and using optimisation techniques weighted in a
+particular direction relative to a fixed point (usually some mic in the array).
+At some point, it clicked that this is really just statistics!
+
+After wrestling with Rust's immature scientific computing libraries for a few weeks,
+and even more reading of my high school maths and university statistics textbooks,
+the result was [Triforce](https://crates.io/crates/triforce-lv2) - an MVDR beamformer
+for the mics found in Apple laptops.
+
+Thanks to the groundwork laid in PipeWire and WirePlumber for speaker support,
+wiring up a DSP chain including Triforce for the microphones was really simple.
+We just had to update the config files, and let WirePlumber figure out the rest!
+
+Did it work? It's Rust, so it worked on the first try! When properly dialled in,
+the mic array is sensitive to signals coming from a "typical" seating position in
+front of the laptop, and mostly rejects noise from any other direction. Try it
+yourself - play some music out of your phone and move it around your laptop. It
+should become suppressed when moved out to the sides or behind the machine.
+
+Once again, a huge thanks to Martin, Eileen, and chaos_princess for their incredible
+work reversing AOP and SEP.
+
+## Fedora Asahi Remix 42 Beta
+Thanks to Davide's work validating builds, we are pleased to announce that Fedora
+Asahi Remix 42 is [now available](https://fedoramagazine.org/announcing-fedora-asahi-remix-42-beta/)
+as a beta! The final release is expected in about a month, bringing us closer than
+ever to releasing at the same time as Fedora. We hope that in the next cycle
+Fedora Asahi Remix 43 will release on the same day as Fedora Linux 43.
+
+## Asahi Linux @ SCaLE
+While at [SCaLE](https://www.socallinuxexpo.org/scale/22x), Neal and Davide managed
+to set up a demonstration of Asahi Linux running on an M2 Mac mini and an M1 Mac Studio
+in the expo hall. Reception was extremely positive, and folks had a blast playing a whole
+bunch of Steam games through muvm and FEX! We even managed to get kids involved by firing
+up Nidhogg, which proved to be the most popular game by far.
+
+## WoAoA
+Some astute users have noticed that ARM64 Windows VMs now work with KVM on
+Asahi! This is thanks to Oliver Upton, who submitted a rather large series of
+patches upstream to enable Arm PMUv3 emulation on Apple SoCs. WoA requires
+PMUv3, and until now we could not emulate it. We quietly cherry-picked those
+patches, and they are now incorporated into our latest kernels. Interested
+parties can try Windows on ARM on Asahi today!
+
+## What does the dxdiag say about its Feature Level?
+It's 12_0! Alyssa recently added sparse binding support to our Vulkan driver,
+which was the last piece of the puzzle for Direct3D Feature Level 12_0 via vkd3d-proton.
+Many more D3D12 games now run with the latest Mesa and FEX rootfs.
+Our Vulkan driver is not yet as mature as our OpenGL driver though, so performance
+and playability vary... but optimisations are coming soon.
+
+## Magic pairing
+Apple Silicon Macs have a neat feature whereby Bluetooth devices remain
+synchronised across all macOS installs, even recoveryOS. Information required
+to pair devices is stored in the machine's NVRAM. macOS checks the NVRAM
+for devices that it doesn't know about, and copies that data. Since
+they see the same Bluetooth controller in the Mac regardless of
+which macOS install is booted, devices will happily connect automatically without
+having to go through the pairing process again. This is really useful for
+ensuring that Bluetooth keyboards and mice work seamlessly across all environments,
+especially in recoveryOS.
+
+To replicate this in Linux, Janne developed [asahi-btsync](https://crates.io/crates/asahi-btsync).
+The tool reads the Bluetooth device information out of NVRAM and injects it into
+BlueZ's configuration. Up until a few weeks ago this was a manual process which
+required running asahi-btsync and connecting to the discovered devices manually.
+This is impractical for input devices which are required to be working for these
+actions.
+
+As of version 2.4, asahi-btsync integrates with systemd and D-Bus to
+fully automate the Bluetooth device synchronisation process. Starting with Fedora
+Asahi Remix 42, all Bluetooth LE devices paired with macOS will be available from
+your first boot - including the initial Fedora Asahi Remix setup!
+
+Do note however that this does not apply to Bluetooth 5.0 devices, which use a
+new authentication and encryption scheme.
+
+## OpenCollective and GitHub Sponsors
+When we stood up our [OpenCollective](https://opencollective.com/asahilinux),
+none of us really knew what to expect. We had hoped to maybe scrape together
+enough support to keep the domains and CDN going, but we dared not hope any harder.
+
+The sheer volume of support and the speed at which it flowed
+in left us floored and humbled beyond measure. Your faith in our work means more
+than can be expressed in words, and we seriously cannot thank you all enough.
+
+The financial support provided via OpenCollective allows us to continue our work
+with confidence. Not only do we have the cash we need to keep the project's
+existing infrastructure online, but we have the resources we have always wanted
+to ensure the project's viability long into the future.
+
+Until now, we have been mostly purchasing machines out of our own pockets. Given
+the nature of what we do, this can mean spending upwards of $10,000 a year on
+Macs. Not only is this unsustainable for us on an individual level, it
+also presents an enormous barrier to entry for talented folks who may not have
+the means to buy such expensive computers. The financial support provided by
+OpenCollective backers enables us to signficantly reduce that financial
+burden. This has already been invaluable for development work.
+
+The M1 MacBook Air is our most popular Mac by far, with almost 14,000 installations
+and counting. This represents almost 30% of the total install base. We couldn't
+possibly release microphone support without supporting it. Being able to simply
+buy the machine and get the work done without worrying about food for the next
+two weeks is the only reason we were able to ship mics in a timely manner.
+
+Buying hardware is not the only game-changing benefit afforded to us by your
+financial support. We can now actually build and maintain the CI farm we have
+sorely needed for years, which will accelerate development. We can afford email
+hosting and other collaborative infrastructure that greatly reduces friction.
+We can go to conferences and events without fear of going into financial stress.
+All of this is necessary to ensure the long-term sustainability of Asahi as a
+project, and none of it would be possible without you.
+
+For those who would prefer to support us via GitHub Sponsors, it's in the works.
+We have put in the request with GitHub to link our Sponsors account to our OpenCollective,
+however this has not yet been approved. Stay tuned for more.
+
+## What's next?
+While this month has been a whirlwind, literally in my case, we've started
+settling down into a rhythm that will work nicely in the near-term. Our primary
+focus is to continue submitting kernel patches upstream. Reducing our maintenance
+burden is the only way we will be able to get back to the fun stuff sustainably.
+
+Neal and Davide will be [presenting](https://events.experiences.redhat.com/widget/redhat/sum25/SessionCatalog2025/session/1731519631980001Xort) at [Red Hat Summit](https://www.redhat.com/en/summit) on 19 May,
+demonstrating Fedora Asahi Remix and the upcoming CentOS Hyperscale Asahi Remix
+to showcase how Asahi has made it easier than ever for developers to start bringing
+their workloads to ARM64 Linux.
+
+We hope to have even more good news for you when Linux 6.15 releases, so stay tuned
+for more updates! Once again, we sincerely thank everyone who has supported us so far.
diff --git a/content/blog/2025/05/15-progress-report-6-15.md b/content/blog/2025/05/15-progress-report-6-15.md
new file mode 100644
index 0000000..524e406
--- /dev/null
+++ b/content/blog/2025/05/15-progress-report-6-15.md
@@ -0,0 +1,166 @@
++++
+date = "2025-05-15T13:00:00+10:00"
+draft = false
+title = "Progress Report: Linux 6.15"
+slug = "progress-report-6-15"
+author = "James Calligeros"
++++
+
+Linux 6.15 is right around the corner, which means it's time for another progress
+report! We have been pretty busy behind the scenes and we have some exciting developments
+to share with you all.
+
+## Fedora Asahi Remix 42 Release
+Last time, we announced that Fedora Asahi Remix 42 was close to release. It has since
+[released](https://fedoramagazine.org/fedora-asahi-remix-42-is-now-available/) and is
+now available to install! The Asahi Installer now offers Fedora Asahi Remix
+42 images by default, and existing users on FAR 40 and 41 are encouraged to upgrade using
+[`dnf system-upgrade`](https://docs.fedoraproject.org/en-US/quick-docs/upgrading-fedora-offline/)
+or Plasma's Discover to start enjoying the latest versions of your favourite
+software. This is also a reminder that Fedora Asahi Remix follows the [Fedora Linux lifecycle policy](https://docs.fedoraproject.org/en-US/releases/lifecycle/),
+and thus Fedora Asahi Remix 40 is now fully end-of-life (EOL).
+
+## Fewer forks, more spoons
+We are pleased to announce that our graphics driver userspace API (uAPI) has been merged
+into the Linux kernel. This major milestone allows us to finally enable OpenGL, OpenCL and Vulkan
+support for Apple Silicon in upstream Mesa. This is the only time a graphics driver's
+uAPI has been merged into the kernel independent of the driver itself, which was kindly
+allowed by the kernel graphics subsystem (DRM) maintainers to facilitate upstream Mesa enablement while
+the required Rust abstractions make their way upstream. We are grateful for this one-off exception,
+made possible with close collaboration with the kernel community.
+
+This means that we will soon sunset our Mesa, virglrenderer, and Flatpak runtime forks. Eliminating these forks lightens
+our maintenance burden, and working directly with upstream Mesa improves the development
+experience for folks working on the userspace graphics stack. It also means that other distros
+like [Debian](https://salsa.debian.org/xorg-team/lib/mesa/-/commit/bcd9afe05d2e31459eb8c1f54b6dda2a257cbf14)
+and [Gentoo](https://github.com/gentoo/gentoo/commit/23e382acf4f7d75e49bc694f409c92385283632f), and
+the [Freedesktop SDK](https://gitlab.com/freedesktop-sdk/freedesktop-sdk/-/commit/13e0add938f4c74887a08ad0ef6493502a8d3913)
+can provide userspace graphics support for Apple Silicon without any additional packaging burden.
+
+Fedora Asahi Remix will drop the forked packages with the upcoming Fedora Linux 43
+based release. We expect that to happen without user intervention. The transition will be
+disruptive for Fedora Rawhide, but Rawhide is not supported or expected to be used on end-user systems.
+
+Upstreaming the uAPI has been an ongoing effort behind the scenes for
+a long time. Making a single change to the uAPI requires commensurate changes to the
+kernel driver, Mesa and virglrenderer. These changes need to be synchronised, since Mesa
+and virglrenderer rely on the uAPI to communicate with the kernel driver. Some keen observers
+may have noticed that [many](https://lore.kernel.org/asahi/20250310-agx-uapi-v1-1-86c80905004e@rosenzweig.io/) [versions](https://lore.kernel.org/asahi/20250313-agx-uapi-v2-1-59cc53a59ea3@rosenzweig.io/) [of](https://lore.kernel.org/asahi/Z-Fn4niI6_Yd06Ze@blossom/) [the](https://lore.kernel.org/asahi/20250323-agx-uapi-v4-1-12ed2db96737@rosenzweig.io/) [uAPI](https://lore.kernel.org/asahi/20250326-agx-uapi-v5-1-04fccfc9e631@rosenzweig.io/) [were](https://lore.kernel.org/asahi/20250327-agx-uapi-v6-1-df6b878a61b2@rosenzweig.io/) [submitted](https://lore.kernel.org/asahi/20250408-agx-uapi-v7-1-ad122d4f7324@rosenzweig.io/) to the kernel mailing lists
+before it was finally merged. Some of the changes between versions were fundamental
+in nature, requiring significant rework to the userspace components and
+kernel driver itself. Alyssa and Janne dedicated countless hours to this endeavour over
+the past few months - making changes, testing them, changing the changes, testing the
+new changes, rinse and repeat. As ever, they have our deepest gratitude and respect
+for pouring so much of their time and effort into closing this out.
+
+## Even more kernel upstreaming!
+The past couple of months have also led to even more kernel patches finding their
+way upstream. Linux 6.15 sees the introduction of the Apple Display Pipe (ADP) display
+controller and Z2 touchscreen digitizer drivers, which together enable Touchbar
+support in the upstream kernel for the M1 and M2 13" MacBook Pros.
+
+Also finding their way upstream are a number of critical patches for supporting various
+functional blocks in Apple's SoCs. PCIe controller support has been merged for the
+T6020 SoC (M2 Pro), which lays the groundwork for supporting the USB-A ports on
+the M2 Pro Mac mini, as well as WiFi and Bluetooth on all M2 Pro devices. WiFi/BT
+additionally depends upon the System Management Controller. Work is ongoing to get
+the SMC driver upstreamed.
+
+Linux 6.15 also includes some patches we require for audio, particularly around the TAS2764 and TAS2770 speaker amp chips.
+These patches add basic support for the Apple-specific variants found in Apple Silicon
+Macs.
+
+## I can't triforce
+Last update, we released microphone support for most laptops. We have since added
+support for the M1 and M2 13" MacBook Pros. Unfortunately, wider release of the microphone
+stack revealed a number of issues. We discovered that the Always-On Processor (AOP) on M2 Pro/Max devices
+differs slightly from the rest of the Apple Silicon family, meaning that microphones
+currently do not work on laptops with those SoCs. Work is underway to sort this out,
+so hang tight!
+
+As discussed last time, Triforce is my naive attempt at implementing a beamformer with
+minor prior knowledge. In my haste to get something working out the door in a
+reasonable timeframe, I made some questionable, _temporary_ engineering decisions.
+Surely I would have time to undo these soon, right?
+
+There is nothing more permanent than a temporary solution. Life got in the way, and I
+found myself with no time to rectify the issues. Ah well, performance is pretty
+bad, but it works well enough...
+
+One of the assumptions I made when building Triforce is that PipeWire's "quantum" (buffer
+size) will always be 1024 samples. At the time, I thought this would be true on every Apple Silicon Mac. Turns out that was a
+bad assumption. If Triforce sees an input buffer that is smaller than 1024 samples,
+it will return nothing to the graph, effectively muting the microphone.
+
+[Frédéric Bour](https://github.com/let-def) ran into this somehow on Fedora Linux 42, and in
+the process of fixing it also took it upon himself to fix many of the other bad choices
+I made in the course of development. The end result is that Triforce should now be more
+accommodating of oddball PipeWire configurations, and about 4 times faster! A huge
+thanks to Frédéric for picking up my slack on this one.
+
+## Upcoming talks
+May brings with it [Red Hat Summit](https://www.redhat.com/en/summit) and
+June brings [DevConf CZ](https://devconf.info/cz). Asahi will be present at both.
+At RH Summit, Neal and Davide will [present](https://events.experiences.redhat.com/widget/redhat/sum25/SessionCatalog2025/session/1731519631980001Xort)
+Fedora Asahi Remix and CentOS Hyperscale Asahi Remix as accessible platforms
+for developers targeting Linux on ARM64. The [talk](https://pretalx.devconf.info/devconf-cz-2025/talk/P3TEBA/)
+at DevConf CZ will focus on the effort to port CentOS Stream to Apple Silicon.
+Both sessions will be available online.
+
+## We're chronically online
+In addition to our [Mastodon](https://social.treehouse.systems/@AsahiLinux) profile, we now
+have Bluesky and LinkedIn accounts. You can follow us at [@asahilinux.org](https://bsky.app/profile/asahilinux.org)
+on Bluesky, and at [Asahi Linux](https://www.linkedin.com/company/asahilinux/)
+on LinkedIn.
+
+## New distro guidelines
+Since the beginning of the project, folks from all walks have worked to support Apple
+Silicon in their favourite distros. This immense interest is a gratifying confirmation
+that the community values our work.
+
+As part of our effort to encourage distros to take up Apple Silicon support, we have
+accommodated all third-party efforts, even allowing distro-specific
+documentation on our project's website. Unfortunately, this has led to
+an impression that we, as the upstream Asahi Linux developers, are involved
+with or otherwise endorse these efforts. This creates both an expectation
+of support and an impression that these efforts are representative of the state
+of Apple Silicon support, or even the state of the broader AArch64 ecosystem. These expectations are
+a significant and growing burden on us, and we need to address it.
+
+We have released [guidelines](https://asahilinux.org/docs/alt/policy/)
+outlining our expectations for distros supporting Apple Silicon. These
+guidelines target official distro projects wishing to collaborate directly with us. We will
+never discourage anyone from adding Apple Silicon support to any distro they choose, but we
+cannot offer official support or endorsement to those projects either.
+
+As a result, we are purging all distro-specific documentation and filtering
+the list of advertised distros to only those which follow the guidelines.
+
+Our long-term goal remains upstreaming everything such that Apple Silicon does not need
+any special treatment or handling.
+
+## Infrastructure ownership
+Until recently, most of our infrastructure was under the control of individuals, including
+domain names. Over the past month, we have been working on transferring as much of this
+as possible away from developers' private accounts and into ownership at the project level.
+This ensures that the project is resilient against any one person leaving.
+It also makes it easier for project expenses to be accounted for. For example, having
+our domain names under the financial ownership of Open Source Collective means that all
+domain-related expenses are processed automatically, rather than needing to paid out
+by a developer and reimbursed.
+
+## Coming up next...
+We have a few items currently pending review on the mailing list, or merged pending
+release in Linux 6.16. Of particlar note are drivers for the SMC and SPMI controller.
+The SMC is important for system shutdown and reboot, GPIO (required to e.g. power on the WiFi board),
+various hardware monitoring sensors, and the RTC. SPMI is a two-wire serial bus similar to I2C.
+Important peripherals, like the power management controller, are attached via this bus.
+Starting with the M3, the USB PD controllers, which negotiate the mode
+(e.g. USB3, Display Port, etc.) with the devices attached to the ports and forward
+it to the PHY and USB controller, are also attached to SPMI rather than
+I2C, making the SPMI controller driver essential for supporting
+those devices. We hope to have more to share in the next progress report.
+
+As always, we want to thank everyone who supports us on [OpenCollective](https://opencollective.com/asahilinux/)
+and [GitHub Sponsors](https://github.com/sponsors/AsahiLinux). None of this would be possible
+without your generous support.
diff --git a/content/code-of-conduct.md b/content/code-of-conduct.md
new file mode 100644
index 0000000..aec54be
--- /dev/null
+++ b/content/code-of-conduct.md
@@ -0,0 +1,51 @@
+---
+title: Code of Conduct
+date: "2021-01-05T20:00:00+09:00"
+draft: false
+---
+
+# Asahi Linux Code of Conduct
+
+Like many Open Source projects and the greater FLOSS community, Asahi Linux is a collaborative open source community comprised of a diverse group of contributors and users from around the globe. We find the contributions, collaborations, and mentorships within our community to be the essential lifeblood of our project and appreciate the efforts of those who participate to nurture and grow those, and all other aspects of our community.
+
+However, when a large and sufficiently diverse group of people work together, there are often cultural, communication, and compatibility issues. In order to minimize conflict, and provide a framework for resolution, we have a brief code of conduct that we ask all participants in the Asahi Linux community adhere to. These rules should apply to everyone, regardless of station within the community, and anyone can serve to remind, or ask the board to help resolve issues.
+
+No list is ever exhaustive, so we encourage members of the Asahi Linux community to adhere to the spirit, rather than the letter, of this code, as that is how it will be enforced. Places where this code may be particularly applicable are GitHub issues and pull requests, IRC, Matrix, mailing lists, Fediverse discussions broadly directed at or between members of the community, and other direct interactions within the community. Any violations, especially continued or flagrant offenses, may affect an individual’s (or organization’s) ability to participate within the Asahi Linux community.
+
+If you feel that someone is in violation of the code of conduct, whether in letter or in spirit, we request that you email as detailed a description as possible of the offense and offending party/parties to [the board](mailto:coc@asahilinux.org). If you have questions, concerns, or any other inquiries please feel free to contact the board.
+
+A large fraction of Asahi Linux consists of contributions to upstream projects. All Asahi Linux contributors are expected to adhere to the respective upstream Codes of Conduct when interacting with such projects, or developing code intended for upstreaming.
+
+## Rules
+
+1. **Be friendly and patient.** We were all new or suffered from a lack of knowledge at one point in time. Please try to remember what it felt like to be on that end, and treat people accordingly.
+
+2. **Be welcoming.** We strive to be a community that welcomes and supports people of all backgrounds and identities. This includes, but is not limited to members of any race, ethnicity, culture, national origin, colour, immigration status, social and economic class, educational level, sex, sexual orientation, gender identity and expression, age, size, family status, political belief, religion, and mental and physical ability.
+
+3. **Be helpful.** By helping others to learn our entire ecosystem is enriched. We encourage members of the Asahi Linux community to mentor each other and help to raise the general level of knowledge in the community whenever possible.
+
+4. **Be considerate.** Your work will be used by other people, and you in turn will depend on the work of others. Any decision you take will affect users and colleagues, and you should take those consequences into account when making decisions. Remember that we’re a world-wide community, so you might not be communicating in someone else’s primary language.
+
+5. **Be respectful.** Not all of us will agree all the time, but disagreement is no excuse for poor behavior and poor manners. We might all experience some frustration now and then, but we cannot allow that frustration to turn into a personal attack. It’s important to remember that a community where people feel uncomfortable or threatened is not a productive one. Members of the Asahi Linux community should be respectful when dealing with other members as well as with people outside the Asahi Linux community.
+
+6. **Be careful in the words that you choose.** We are a community of professionals, and we conduct ourselves professionally. Be kind to others. Do not insult or put down other participants. Harassment and other exclusionary behavior aren’t acceptable. This includes, but is not limited to:
+ * Violent threats or language directed against another person.
+ * Discriminatory jokes and language.
+ * Posting sexually explicit or violent material.
+ * Posting (or threatening to post) other people’s personally identifying information (“doxing”), regardless of whether it is publicly available.
+ * Personal insults, especially those using racist, sexist, or otherwise discriminatory terms.
+ * Deliberately referring to others by names or pronouns counter to their identity.
+ * Unwelcome sexual attention.
+ * Advocating for, or encouraging, any of the above behavior.
+ * Repeated harassment of others. In general, if someone asks you to stop, then stop.
+
+7. **When we disagree, try to understand why.** Disagreements, both social and technical, happen all the time and Asahi Linux is no exception. It is important that we resolve disagreements and differing views constructively. Remember that we’re different. The strength of Asahi Linux comes from its varied community, people from a wide range of backgrounds. Different people have different perspectives on issues. Being unable to understand why someone holds a viewpoint doesn’t mean that they’re wrong. Don’t forget that it is human to err and blaming each other doesn’t get us anywhere. Instead, focus on helping to resolve issues and learning from mistakes.
+
+## Consequences
+
+1. Except in flagrant or otherwise egregious cases, the first infraction will result in a verbal warning. Everyone slips up or acts out of frustration at times, we just ask that you work to not repeat the behavior.
+2. A second infraction (or more flagrant first offense, as determined by the board) will have an anonymized summary of the interaction published as a way to educate the community and serve as a reminder that adverse behavior will not be tolerated.
+3. A third infraction (or especially egregious first offense, as determined by the board) will result in temporary suspension from all avenues of Asahi Linux community participation for 4 weeks. This will include, but is not limited to, IRC, Matrix, and GitHub issues/PRs.
+4. Continued infractions will be dealt with on a case-by-case basis, but could result in permanent suspension from the Asahi Linux community.
+
+This text is adapted from the [Ceph Code of Conduct](https://ceph.io/community/code-of-conduct/), which itself credits [Django Project](https://www.djangoproject.com/conduct/) for the original inspiration of this document and the [Ada Initiative](https://adainitiative.org/) for expanding the fight for equality and civility within FLOSS communities and beyond.
diff --git a/content/community.md b/content/community.md
new file mode 100644
index 0000000..2910893
--- /dev/null
+++ b/content/community.md
@@ -0,0 +1,40 @@
+---
+title: Community
+date: "2021-01-05T20:00:00+09:00"
+draft: false
+---
+
+# Community
+
+If you're interested in the project, you're welcome to drop by! Check out [ways in which you can contribute](/contribute).
+
+Please remember that all community members are expected to abide by our [Code of Conduct](/code-of-conduct).
+
+## IRC
+
+Most development and project discussion takes place on IRC. We have several channels on the OFTC IRC network:
+
+* #asahi [[logs](https://oftc.irclog.whitequark.org/asahi)] - General project discussion
+* #asahi-dev [[logs](https://oftc.irclog.whitequark.org/asahi-dev)] - Development discussion
+* #asahi-re [[logs](https://oftc.irclog.whitequark.org/asahi-re)] - Binary decompilation/tainted discussion
+* #asahi-gpu [[logs](https://oftc.irclog.whitequark.org/asahi-gpu)] - GPU reverse engineering and development
+* #asahi-alt [[logs](https://oftc.irclog.whitequark.org/asahi-alt)] - Discussion and support for unofficial third-party distro ports
+* #asahi-stream - Chatroom for people to talk during the devs' video streams
+
+Even if you don't plan to speak, feel free to join and idle in the above channels if you'd like to follow the discussion.
+
+**Note: Due to spambot attacks, we currently only allow users connecting with TLS to join the channels. Please make sure your IRC client is set to enable TLS and connect to irc.oftc.net on port 6697**.
+
+## Matrix
+
+The Fedora-specific Asahi discussions take place in Matrix on Fedora infra:
+* [#asahi-devel:fedoraproject.org](https://matrix.to/#/#asahi-devel:fedoraproject.org) - Fedora Asahi Development. IRC bridge: #fedora-asahi-dev
+* [#asahi:fedoraproject.org](https://matrix.to/#/#asahi:fedoraproject.org) - Fedora Asahi general discussion/support
+
+## Documentation
+
+Our working documentation is maintained in a [documentation site](/docs) built from [GitHub](https://github.com/AsahiLinux/docs) using [MkDocs](https://mkdocs.org).
+
+## Mastodon (Fediverse)
+
+You will also find official announcements and information on the [Asahi Linux Mastodon account](https://social.treehouse.systems/@AsahiLinux).
diff --git a/content/contribute.md b/content/contribute.md
new file mode 100644
index 0000000..afef09b
--- /dev/null
+++ b/content/contribute.md
@@ -0,0 +1,30 @@
+---
+title: Contribute
+date: "2021-01-05T20:00:00+09:00"
+draft: false
+---
+
+# Contribute
+
+Asahi Linux is an open source project, and it would not be possible without the support of the community. We encourage contributors of all skill sets and backgrounds!
+
+All contributors are expected to abide by our [Code of Conduct](/code-of-conduct) and our [Copyright and Reverse Engineering policy](/copyright).
+
+## New to this kind of thing?
+
+Are you interested in this kind of project, but you've never worked on something like this before? We were all like that at one point! The best way to learn how a low-level reverse engineering and development project like this works is to get involved. It might be intimidating at first, but don't worry. Join the [IRC channels](/community) and watch to see how things work. If you find an area which you find interesting, you can poke around yourself! If you feel like you can contribute to anything, just say so!
+
+Here are some suggestions to get you started:
+
+* Documentation: Reverse engineering often results in ugly brain-dump text files full of information, but we don't always have the time to clean things up into a nice wiki page. Helping out here is a good opportunity to get familiar with the subject, and you can ask questions to help shape the documentation and ensure it is accurate.
+* Verification: Notes and documentation may have mistakes or be hastily written! It is always useful to have a second set of eyes go over the information, then try things out on the real hardware and see if it is correct. This is a good way to play around with the real hardware and understand how things work, and help find problems along the way!
+* Testing: Does the code actually work? We need you to find out if it's broken in some way :-)
+* Completeness: There are often gaps in what we find out - what does this bit do? What happens if you do more than one thing at once? You can look at cases we haven't tested yet and help complete the documentation and code.
+
+## Already been here before?
+
+Feel free to jump right and help us out - there is lots of work to do. A brief introduction would be helpful so that we can get to know you better. Let us know what you are experienced with and we can point you at specific areas you can help with.
+
+## Prefer to help financially?
+
+Head over to our [Open Collective](https://opencollective.com/asahilinux) to donate. Every little bit counts!
diff --git a/content/copyright.md b/content/copyright.md
new file mode 100644
index 0000000..297238f
--- /dev/null
+++ b/content/copyright.md
@@ -0,0 +1,124 @@
+---
+title: Copyright & Reverse Engineering
+date: "2021-01-05T20:00:00+09:00"
+draft: false
+---
+
+# Copyright policy
+
+Asahi Linux is an open source project, and all contributions must follow the appropriate open source licenses.
+
+These contribution rules are particularly important for code that is to be upstreamed into other projects, to maintain a clean paper trail of the licensing.
+
+## Licensing
+
+Code developed for Asahi Linux itself should be licensed under a permissive license that allows other projects to take advantage of the code without running into license compatibility problems. The specific licenses are subject to being decided on a case-by-case basis, but we will usually use a permissive license such as the MIT license.
+
+Code developed for other open source projects must be licensed under that same project's license, and follow licensing/header/authorship conventions appropriate for that project. However, specific modules developed by Asahi Linux contributors (such as entire drivers or submodules) should be dual-licensed under a permissive license such as MIT, to ensure that they can be ported or reused within other projects.
+
+For original code, we use [SPDX license identifiers](https://spdx.github.io/spdx-spec/v2.3/using-SPDX-short-identifiers-in-source-files/) to record the license of individual files in a concise way. Files should have header of this form (with whatever license information is appropriate):
+
+```// SPDX-License-Identifier: GPL-2.0+ OR MIT```
+
+No specific authors should be listed in source code files themselves, as this is hard to maintain and unlikely to remain accurate. For top-level and informational places where a copyright statement is needed, such as the MIT license text or "about" style dialogs, the code should be attributed to "The Asahi Linux Contributors".
+
+We do not require contributors to accept any kind of CLA, nor do we require any kind of copyright assignment. You retain all copyright ownership of any code you write. These are merely conventions about how the origin of the code should be documented in version control and files.
+
+## Attribution
+
+Asahi Linux uses Git for managing source code, and the Git history serves as a record of authorship. The Git "Author" field should reflect the primary author of a change - if you commit a change authored by another person, you should ensure they are listed as the author. If a change is authored by multiple people, you should add one or more `Co-Developed-by: Foo Bar ` lines at the end of the commit message.
+
+Non-Git releases of the software will be arranged to have an automatically generated authorship file containing a list of all Git contributors.
+
+In order to certify the origin of contributions, all contributors are required to accept the Developer's Certificate of Origin 1.1:
+
+> ## Developer’s Certificate of Origin 1.1
+>
+> By making a contribution to this project, I certify that:
+>
+> * The contribution was created in whole or in part by me and I have the right to submit it under the open source license indicated in the file; or
+> * The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same open source license (unless I am permitted to submit under a different license), as indicated in the file; or
+> * The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it.
+> * I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved.
+
+To certify this, add a line to the end of your Git commit message as follows:
+
+```
+Signed-off-by: Random J Developer
+```
+
+This can be automated by simply using `git commit -s`.
+
+Real names are not required for authorship or sign-off info. We encourage people to use a name they are commonly known by (e.g. a name you commonly use to interact in similar spaces), as that helps establish trust.
+
+# Reverse engineering policy
+
+We are committed to ensuring that all source code and documentation produced by the project is legal and free of copyright violations and other legal problems. In order to ensure this, we have a policy that all contributors must follow, particularly if they are doing certain kinds of reverse engineering.
+
+"Clean-room" reverse engineering is often considered the gold standard to ensure good legal standing for a reverse engineering project. This involves having separate teams, one of which does the reverse engineering and writes documentation, and the other implements that documentation into the final product. This approach is not a legal requirement to ensure that the final product is free from copyright violations, nor does it absolutely guarantee such a result, but it is a fairly strong legal defense should copyright questions arise.
+
+We recognize that a true textbook clean-room approach is not sustainable for most open source projects of this nature. Thus, we aim to ensure that Asahi Linux's code and contributions are effectively equivalent to what a clean-room approach would produce, without mandating the overhead of a true clean-room process.
+
+In order to protect contributors and developers who want to stay away from such subjects, we require that all reverse engineering discussion happen in the #asahi-re and #asahi-gpu (for GPU RE) IRC channels.
+
+## Non-reverse-engineering development
+
+If you are merely looking at existing Asahi Linux code and improving it (without taking or referencing code from anywhere else), you are not reverse engineering anything, and you do not need to worry about anything else. Just make sure to follow the [Copyright policy](#copyright-policy).
+
+## Referencing other open source code
+
+This is generally OK, but you should not copy and paste any actual code unless the license is compatible and the origin of the code is documented.
+
+In particular, be careful of open source dumps from Apple, as they are often licensed under the APSL, which is not GPL compatible. Asahi Linux does not allow any APSL code to be used directly. You can use it as a reference for how things work, and you can take inspiration from register names (since those are effectively hardware documentation; we do not consider mere last-level register names to be copyrightable), but do not copy whole `#define` blocks or include files, other code, or reimplement identical code flows or algorithms. Follow sensible downstream register naming conventions (such as prefixes).
+
+For example, [this](https://github.com/opensource-apple/xnu/blob/master/pexpert/pexpert/arm64/arm64_common.h#L10) register, as documented in XNU include files, should be defined like this when used for Linux:
+
+```
+#define SYS_HID0 sys_reg(3, 0, 15, 0, 0)
+```
+
+Or perhaps:
+
+```
+#define SYS_APL_HID0 sys_reg(3, 0, 15, 0, 0)
+```
+
+Strictly speaking, referencing incompatibly-licensed code can run into similar copyright issues to binary reverse engineering as detailed below; please make sure to read that section to know what not to do.
+
+Internal tools intended only for exploration and not to be released to end-users are allowed to use APSL code, including taking APSL releases directly and modifying them, as long as all licensing requirements are met. For example, taking an APSL release, modifying it to aid in reverse engineering, and using the result back in macOS is fine, and we can host such changes as an Asahi Linux repo, but they cannot become an actual release of the project.
+
+**Be cautious of open source code that works with Apple-specific undocumented file formats, hardware, and protocols**. Such code should, out of an abundance of caution, be treated as if it were incompatibly licensed, like APSL code. The reason is that we cannot guarantee that said code was not the product of reverse engineering that would violate this policy. Therefore, you should not copy and paste or otherwise directly incorporate such code, even if the license is ostensibly compatible. Generally speaking, it is unlikely that directly incorporating code of this nature would offer more than a minor time saving; they are more useful as stand-alone tools and as code-as-documentation. It is okay to use such third-party stand-alone tools during development, or to fork and patch them for exploration, like APSL code - if a copyright problem surfaces, we can easily remove said tools if they have not tainted other project code. Cases where there is significant value to be derived from integrating such code will be reviewed and audited on a case by case basis by project leads.
+
+Put another way: we want to ensure not just license compatibility, but also compatibility with this policy itself. Therefore, we do not allow combining code developed under this policy with code not developed under this policy in cases where a policy violation could have plausibly occurred.
+
+## Hardware exploration
+
+One particularly safe way to reverse engineer without running into copyright issues is to simply probe the hardware to find out what it does. Any knowledge gained this way is safe to use when writing open source code. For example, dumping register areas, twiddling bits, and seeing what other bits change and how the hardware behaves. This is particularly useful to complete knowledge of a piece of hardware that is only partially understood, and can often lead to insight that is not used and thus not present in the vendor's binary code.
+
+## Register and data tracing
+
+When blind probing isn't enough, another effective trick is to run macOS and look at what it does. This can be done by dumping hardware register state before and after an action, or by intercepting data between different components, such as the userspace graphics stack and the kernel graphics driver, and dumping or modifying data.
+
+Register values and command buffers are usually not considered copyrightable, so it is safe to use this approach to obtain the necessary information to write an open source driver.
+
+Exceptions include cases where code or large blobs of data are uploaded to the hardware. For example, a binary shader obtained by compiling your own GPU shader source code would normally not be copyrightable, but if it contains significant sections of code inserted by the compiler (for example, significant scaffolding or algorithms to implement a particular feature), then that part may be. Use your best judgement in these cases, and do not copy long instruction sequences that do not directly correspond to code you have written in source form.
+
+Similarly, if any firmware blobs are uploaded to the hardware, those cannot be copied as-is, and we must figure out how to approach them on a case-by-case basis.
+
+## Binary disassembly and decompilation
+
+Asahi Linux does not ban binary disassembly and decompilation as a means to obtain knowledge required to write open source implementations. However, this is a dangerous road. We have seen many cases of "open source" code that was developed by direct translation of reverse engineered binary code. This is unacceptable, and would put the entire project and upstream projects at risk.
+
+Since the Asahi Linux project board is ultimately responsible for certifying the origin of code upstreamed as part of the project, we need to ensure that any instances of this approach are following a process that does not result in copyright infringement. We have previously seen other projects take contributions that turned out not to be clean, putting those projects into legal doubt - this was often discovered long after the code was contributed, as the origin of the code may not be immediately apparent. For this reason, we do not currently allow contributions of code developed concurrently with binary reverse engineering except from specific trusted contributors. Please contact [the board](mailto:board@asahilinux.org) for details.
+
+All other contributors are required to follow the textbook "clean-room" approach: If you would like to disassemble/decompile components in order to contribute to the project, you must make that decision for a specific component/area with care, and once you do, you are expected to only contribute to that area by writing clean documentation of the hardware, and let other project members implement it.
+
+Especial caution must be applied for the graphics stack: contributors **must not disassemble or decompile userspace graphics driver binaries**, including the proprietary LLVM-based shader compiler and Metal itself, even to produce documentation for clean room Mesa development. The reason for this is two-fold. One, black box data tracing is a highly effective technique that can be relied on for reverse-engineering in isolation, causing disassembly to be needless risk. Two, userspace code tends to be more algorithmic and original in nature, compared to kernel code, rendering these techniques especially risky. Remember, the goal is to reverse-engineer the GPU hardware, not to reverse-engineer the proprietary driver software.
+
+Contributors doing binary reverse engineering are responsible for any legal consequences of their work, including any consequences of the license associated with said code.
+
+**Important**: In order to ensure the legal safety of project members that don't want to involve themselves in this reverse engineering approach, *all* such discussion is allowed **only** in the #asahi-re IRC channel. This will be strictly enforced, and work involving binary RE on other #asahi-* channels will lead to a kick or a ban. Additionally, do not paste any decompiled/disassembled code into the IRC channels. These channels are publicly logged.
+
+## Usage of unreleased materials
+
+Asahi Linux absolutely forbids the usage of any copyrighted materials not available to the public during reverse engineering. This includes any leaked software (in source or binary form), unreleased documentation, non-public releases (such as restricted betas), etc. Project contributors are expected to refrain from acquiring or using any such content. Only materials that are explicitly made available to the public at large may be used. This applies to materials from both Apple and any other third parties.
diff --git a/content/fedora.md b/content/fedora.md
new file mode 100644
index 0000000..99cb7e4
--- /dev/null
+++ b/content/fedora.md
@@ -0,0 +1,267 @@
+---
+title: Fedora Asahi Remix
+date: "2025-04-15T11:27:00-04:00"
+draft: false
+body_class: "landing fedora"
+layout: landing
+---
+
+
+
+
Introducing
+
Fedora Asahi Remix
+
The most polished Linux® for Apple Silicon Macs.
+
Install from macOS
+
curl https://alx.sh | sh
+
+
+
+
+
+
+
+
+##
Fedora Linux 42 + Apple Silicon = Fedora Asahi Remix
+
+Fedora Asahi Remix is the result of a close multi-year collaboration between the Asahi Linux project and the [Fedora Project](https://fedoraproject.org/). We've worked hard in order to bring you a fully integrated distro, cooperating closely to get improvements and bug fixes to users as quickly as possible. All of our Asahi platform-specific packages are in upstream Fedora and fully supported in Fedora Linux 42.
+
+With Fedora's excellent 64-bit ARM support and mature development process, you can expect a solid and high-quality experience without any unwanted surprises. Fedora Asahi Remix is based on Fedora Linux 42, the latest Fedora Linux release with the newest software versions across the board. All M1 and M2 series MacBook, Mac Mini, Mac Studio, and iMac devices are supported.
+
+
+
+
+##
Fedora Asahi Remix ❤️ KDE Plasma
+
+We are proud to offer [KDE Plasma](https://kde.org/plasma-desktop/) as our flagship desktop environment. With leading edge Wayland support and a highly customizable experience plus wide support for Apple hardware features, KDE Plasma is a joy to use on Apple Silicon.
+
+Want to use Night Color to keep your screen from disrupting your sleep cycle? No worries, it just works. Tweak your trackpad settings for a more comfortable experience? Everything's right there in System Settings. Are things on screen too big or too small? Just adjust the display scale to your heart's content, even in 5% increments. We've worked with the KDE project to bring you bug fixes and improvements to improve platform support, and we've also built a custom Calamares-based initial setup wizard so you can be up and running in no time with minimal fuss.
+
+Fedora Linux 42 comes with [KDE Plasma 6.3](https://kde.org/announcements/plasma/6/6.3.0/), with the latest patches and improvements to provide *the* premier desktop experience.
+
+Rather use [GNOME](https://www.gnome.org/)? No worries, we've got you covered with [GNOME 48](https://release.gnome.org/48/). Or, if you prefer to roll your own desktop configuration or want to set up a headless server, our Minimal and Server images will let you set things up exactly the way you want to.
+
+
+
+
+##
100% Wayland Experience
+
+Whether you're a KDE enthusiast or a GNOME lover, Fedora Asahi Remix comes right out of the box with a 100% [Wayland](https://wayland.freedesktop.org/) environment, bringing you the newest desktop and display server technologies, which are a perfect match for Apple hardware. You'll get a buttery smooth desktop, with absolutely no tearing or glitching, just like on macOS. Experience seamless HiDPI support in our KDE Plasma builds, even across multiple displays with different display scales.
+
+And with upcoming improvements in the Wayland ecosystem, we'll be able to support new technologies such as HDR and display notches, as well as proper display calibration. Have some X11 apps to run? No worries, XWayland is available and fully supported as a bridge for legacy applications.
+
+
+
+
+##
OpenGL, deprecated? Not here
+
+
+
+
+
+
+
+
+Fedora Asahi Remix ships the world's first and only certified conformant [OpenGL 4.6](https://www.khronos.org/conformance/adopters/conformant-products/opengl#submission_347), [OpenGL ES 3.2](https://www.khronos.org/conformance/adopters/conformant-products/opengles#submission_1045), [OpenCL 3.0](https://www.khronos.org/conformance/adopters/conformant-products/opencl#submission_433), and
+[Vulkan 1.4](https://www.khronos.org/conformance/adopters/conformant-products/vulkan#submission_812) for Apple Silicon.
+
+We support open graphics standards and test against official and industry-standard test suites, which means you can be confident that your apps and games will run correctly and render as they're intended to. Fedora Asahi Remix unlocks the full potential of Apple Silicon graphics, well beyond what is possible by layering on top of vendor-proprietary APIs like Metal.
+
+
+
+
+##
The best Linux laptop audio you've ever heard
+
+We've worked hard to pioneer the world's first fully integrated DSP solution for the desktop Linux ecosystem. Just install Fedora Asahi Remix and enjoy high-quality audio right out of the box, no setup needed. We've worked together with the [PipeWire](https://pipewire.org/) and [WirePlumber](https://gitlab.freedesktop.org/pipewire/wireplumber) projects to add support for fully automatic and transparent DSP configuration, and then individually measured and calibrated 8+ different machine models, designing a customized DSP filter configuration for each one.
+
+With our in-house [Bankstown](https://github.com/chadmed/bankstown) bass boost technology and our own pioneering open source [Smart Amp](https://github.com/AsahiLinux/speakersafetyd) implementation to safely provide full loudness and dynamic range, the result is the best audio you've ever heard on a Linux laptop. And we've even optimized the scheduling and power consumption of the DSP processing, so you'll get excellent battery life while playing back audio.
+
+
+
+
+
* Local dimming available on 14" and 16" models. Maximum 60Hz refresh rate on all models. HDR/120Hz not yet supported.
+
† Available on 13" models only.
+
‡ Available on 14" and 16" models only.
+
+
+
Chips
+
+
M1
+
M2
+
M2 Pro
+
+
Features
+
+
Headset Jack
+
Speaker
+
USB Type A (3.0)
+
USB Type C (3.0)
+
HDMI
+
Ethernet (1/10 Gbps)
+
Wi-Fi
+
Bluetooth
+
USB-C Displays
+
Thunderbolt / USB4
+
+
+
+
Chips
+
+
M1 Max
+
M1 Ultra
+
M2 Max
+
M2 Ultra
+
+
Features
+
+
Headset Jack
+
Speaker
+
USB Type A (3.0)
+
USB Type C (3.0)
+
HDMI
+
SD Card
+
Ethernet (10 Gbps)
+
Wi-Fi
+
Bluetooth
+
USB-C Displays
+
Thunderbolt / USB4
+
+
+
+
Chips
+
+
M1
+
+
Features
+
+
Display
+
Headset Jack
+
Speakers
+
Camera
+
USB Type C (3.0)
+
Ethernet (1 Gbps)
+
Wi-Fi
+
Bluetooth
+
USB-C Displays
+
Thunderbolt / USB4
+
Microphone
+
+
+
+
+
diff --git a/content/governance.md b/content/governance.md
new file mode 100644
index 0000000..3e2912d
--- /dev/null
+++ b/content/governance.md
@@ -0,0 +1,35 @@
+---
+title: Governance
+date: "2025-02-12T00:00:00+00:00"
+draft: false
+---
+
+# Governance
+
+Asahi Linux is led by our community of open source developers. If you want to work on something, work on it! We welcome contributors from different backgrounds. By and large, we make change by “doing”. Asahi Linux is about the code, and the code comes from anyone who wants to write it. Development uses a “lazy consensus” model: the work happens when people do it. Other developers can veto to force a discussion, but developers don’t need to chase people for trivial issues.
+
+To support that code, we need infrastructure and funding, to run servers and support developers. While development happens with a “lazy consensus” model, these logistical issues are governed by our project board.
+
+There are seven board members, aside from temporary vacancies. The current members are:
+
+* [Alyssa Rosenzweig](https://rosenzweig.io) (treasurer).
+* [Davide Cavalca](https://github.com/davide125) (administrator).
+* [Neal Gompa](https://royalgeekworld.com/) (secretary, treasurer).
+* [James Calligeros](https://social.treehouse.systems/@chadmed).
+* [Janne Grunau](https://social.treehouse.systems/@janne) (administrator).
+* Sasha Finkelstein.
+* [Sven Peter](https://social.treehouse.systems/@sven) (administrator).
+
+The board is responsible for project governance, infrastructure, and money. It also acts as the ultimate arbiter in case of conflict, including code-of-conduct enforcement. The board meets monthly by video call to do business in meetings. Our meeting minutes are public.
+
+The board appoints specific members to the following roles by majority vote:
+
+* Treasurers have access to our [Open Collective](https://opencollective.com/asahilinux) and implements the financial decisions the board makes by vote. They do not themselves decide how to spend money.
+* The secretary schedules meetings, drives meetings, and maintains meeting minutes.
+* Administrators have access to project infrastructure, including our servers. Like developers, they operate by “lazy consensus”.
+
+The board votes on how money should be spent. If the money’s recipient is a board member, that member is ineligible for the vote. For example, if a developer needs a new Asahi development machine, the rest of the board would approve that expense. The treasurer then handles the transaction. Finally, the board audits transactions after the fact, aided by Open Collective’s transparent documentation of transactions.
+
+Board members may be added (when there are vacancies) or removed by vote. These bylaws may be amended by vote. A vote passes with the approval of four members.
+
+It is sometimes necessary to vote between meetings, occurring in our [public Matrix room](https://matrix.to/#/#asahi-board:matrix.org).
diff --git a/content/merch.md b/content/merch.md
new file mode 100644
index 0000000..c8a79fe
--- /dev/null
+++ b/content/merch.md
@@ -0,0 +1,9 @@
+---
+title: Merch
+date: "2025-06-04T07:33:19-07:00"
+draft: false
+---
+
+# Asahi Linux merch
+
+If you'd like to buy Asahi Linux merch, you can do so on our [HELLOTUX store](https://www.hellotux.com/asahi). A portion of each sale is donated to the project.
diff --git a/content/support.md b/content/support.md
new file mode 100644
index 0000000..1a8d90b
--- /dev/null
+++ b/content/support.md
@@ -0,0 +1,14 @@
+---
+title: Support
+date: "2025-06-04T07:33:19-07:00"
+draft: false
+---
+
+# Support Asahi Linux
+
+The Asahi Linux project is funded by individuals like you. If you would like to support us financially, head over to our project [Open Collective](https://opencollective.com/asahilinux) or to our [GitHub Sponsors](https://github.com/sponsors/AsahiLinux). You can also [buy Asahi Linux merch](/merch), which supports the project with each sale.
+
+Porting Linux to Apple Silicon is no small task. Financial support will allow
+us to buy hardware and fund contributors, allowing the project to advance at a
+steady pace and ensure that everything is paid the proper attention.
+
diff --git a/cookie-policy/index.html b/cookie-policy/index.html
deleted file mode 100644
index 3e1304f..0000000
--- a/cookie-policy/index.html
+++ /dev/null
@@ -1,752 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-Cookies – UwUntu
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Asahi Linux and the open source projects it depends on are made possible by communities of volunteers. All contributors are welcome, of any skill level!