Monday 27 May 2024

Guide to Asahi Linux Fedora running Steam | microVM

Introduction

I heard about Asahi Linux back in the early days and became one of its followers/supporters.  I believe having the arm ecosystem and an option to run linux on mac systems a must first step in many developments including fully adapability in an newer architecture.  This guide is for owners of M1 or M2 macs running fedora linux 40 in order to run steam games.

For the past little while I have been diving into this Linux stack trying to replicate the rumored steam installation and running of various games on Fedora Linux on a mac. The source of this material is from slp's blog and also Rob Clark’s XDC 2022 talk about Virtgpu DRM native context, a novel technique that brings close-to-native GPU performance to VMs.

The problem with Asahi Linux is a paging size problem in running steam which requires 4k pages while the operating system uses 16k pages.  The x86_64 games on steam runs on 4k size pages.  Understand the experimental nature of doing this. Do not bug the Asahi Liux Developers about this.  This guide can break at any time. It is working as of May 2024.

The Guide

Install Fedora Remix 40

https://asahilinux.org/fedora/

Install Distrobox

sudo dnf copr enable alciregi/distrobox

sudo dnf install distrobox

Use distrobox to create image

    export DBX_CONTAINER_MANAGER=podman
    distrobox create --image quay.io/fedora/fedora-toolbox:40-aarch64 --name asahi-krun --volume ~/.config/pulse


Enter Distrobox

    distrobox enter asahi-krun

When ready your prompt should look like this [username@asahi-krun ~]$

Install krun and dependencies inside the container

sudo dnf copr enable slp/asahi-mesa-wip
sudo dnf copr enable teohhanhui/asahi-krun
sudo dnf --best install alsa-lib alsa-plugins-pulseaudio alsa-utils dhclient eglinfo glmark2 glx-utils libkrun mesa-demos mesa-dri-drivers passt pipewire-libs pulseaudio pulseaudio-libs pulseaudio-utils sommelier virglrenderer xorg-x11-server-Xwayland --exclude pipewire
cd ~/Downloads
git clone https://github.com/slp/krun.git
cd krun
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
. ~/.cargo/env
sudo dnf group install c-development
sudo dnf install clang-devel libkrun-devel llvm-devel
cargo build --release
sudo cp target/release/krun{,-guest} /usr/local/bin/
sudo chmod +x /usr/local/bin/krun{,-guest}
sudo chown -R $USER: ~/.config/pulse

Save the krun file from this gist as ~/.local/bin/krun, then chmod +x ~/.local/bin/krun. This will be your entry point to run anything inside krun VM.

krun


#!/bin/sh
if [ "$(cut -d '' -f1 < /proc/1/cmdline)" = '/init.krun' ]; then
echo >&2 'cannot run krun inside krun VM'
exit 1
fi
if pidof -q /usr/local/bin/krun; then
echo >&2 'cowardly refusing running more than 1 krun VM to avoid memory contention'
exit 1
fi
if [ -z "${DBX_CONTAINER_MANAGER}" ]; then
export DBX_CONTAINER_MANAGER=podman
fi
if [ -n "${CONTAINER_ID}" ]; then
container_name="${CONTAINER_ID}"
# if the variable is not set, let's fall back to some tricks.
elif [ -e /.dockerenv ]; then
# we're in docker, let's use this trick
container_name=$(grep "memory:/" < /proc/self/cgroup | sed 's|.*/||')
elif [ -e /run/.containerenv ]; then
# we're in podman or lilipod, use this other trick
container_name=$(grep "name=" /run/.containerenv | cut -d'=' -f2- | tr -d '"')
fi
if [ -z "${container_name}" ]; then
exec "/usr/bin/distrobox-enter" -n asahi-krun -- '/usr/local/bin/krun' "$@"
elif [ -n "${container_name}" ] && [ "${container_name}" != "asahi-krun" ]; then
exec distrobox-host-exec "$HOME/.local/bin/krun" "$@"
else
exec '/usr/local/bin/krun' "$@"
fi 

Save the krun-guest file from this gist as ~/.local/bin/krun-guest, then chmod +x ~/.local/bin/krun-guest. We use this file to override some things while running inside the krun VM (for now).

krun_guest


#!/bin/sh
KRUN_GUEST=/usr/local/bin/krun-guest
if ! [ "$(cut -d '' -f1 < /proc/1/cmdline)" = '/init.krun' ]; then
echo >&2 'krun-guest must be run inside krun VM'
exit 1
fi
# https://github.com/slp/krun/pull/12
ulimit -n 524288
wrapper=$(mktemp)
{
echo 'set -e';
echo 'mkdir -p ${XDG_RUNTIME_DIR}/pulse';
echo 'rm -f ${XDG_RUNTIME_DIR}/pulse/pid';
echo 'pulseaudio -D --load="module-alsa-card device_id=0" --exit-idle-time=-1';
echo 'exec "$@"';
} > "$wrapper"
chmod +x "$wrapper"
user=$1
uid=$2
gid=$3
shift 3
exec "${KRUN_GUEST}" "$user" "$uid" "$gid" "$wrapper" "$@"

Install fex-emu inside the container

    sudo dnf copr enable teohhanhui/fex-emu
    sudo dnf install fex-emu

Save the FEXBash file from this gist as ~/.local/bin/FEXBash, then chmod +x ~/.local/bin/FEXBash. This will be your entry point to run commands in the FEX environment. Tip: Don't use FEXBash in your shell scripts, as it does not properly handle word splitting. Use krun FEXInterpreter or krun FEXInterpreter sh instead.

FEXBash


#!/bin/sh
if [ "$(cut -d '' -f1 < /proc/1/cmdline)" = '/init.krun' ]; then
exec '/usr/bin/FEXBash' "$@"
fi
if [ -z "${DBX_CONTAINER_MANAGER}" ]; then
export DBX_CONTAINER_MANAGER=podman
fi
if [ -n "${CONTAINER_ID}" ]; then
container_name="${CONTAINER_ID}"
# if the variable is not set, let's fall back to some tricks.
elif [ -e /.dockerenv ]; then
# we're in docker, let's use this trick
container_name=$(grep "memory:/" < /proc/self/cgroup | sed 's|.*/||')
elif [ -e /run/.containerenv ]; then
# we're in podman or lilipod, use this other trick
container_name=$(grep "name=" /run/.containerenv | cut -d'=' -f2- | tr -d '"')
fi
if [ -z "${container_name}" ]; then
exec "/usr/bin/distrobox-enter" -n asahi-krun -- krun '/usr/bin/FEXBash' "$@"
elif [ -n "${container_name}" ] && [ "${container_name}" != "asahi-krun" ]; then
exec distrobox-host-exec "$HOME/.local/bin/FEXBash" "$@"
else
exec krun '/usr/bin/FEXBash' "$@"
fi

If you do krun myprogram where myprogram is an x86(-64) executable, it'll automatically get run using FEX, thanks to binfmt_misc rules. Note: This would not work for programs like steam which are only installed inside the FEX RootFS.

Set up FEX RootFS

    krun FEXRootFSFetcher

Then follow the instructions:
Choose y to download.
Choose 1 for Fedora 40.
Choose 1 to extract.
Choose y to set as default.

Exit distrobox container

    exit

chroot into FEX RootFS

sudo dnf install qemu-user-static
cd ~/.fex-emu/RootFS/Fedora_40
sudo ./unbreak_chroot.sh


You should have seen Chrooting into container message, and your terminal prompt should look something like:[root@Han-MacBook-Air /]#

Install Steam in FEX RootFS

dnf copr enable slp/asahi-mesa-wip

sed 's/\[\(copr:copr\.fedorainfracloud\.org:slp:asahi-mesa-wip\)\]/[\1.i386]/;s/\$basearch/i386/' /etc/yum.repos.d/_copr:copr.fedorainfracloud.org:slp:asahi-mesa-wip.repo > /etc/yum.repos.d/_copr:copr.fedorainfracloud.org:slp:asahi-mesa-wip.i386.repo

dnf --best install alsa-utils eglinfo glmark2 glx-utils mesa-demos mesa-dri-drivers mesa-libEGL mesa-libEGL-devel mesa-libgbm mesa-libGL mesa-va-drivers pulseaudio-utils

dnf install https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm

dnf install dbus-x11 steam xdg-user-dirs

Exit from FEX RootFS chroot

    exit
    sudo ./break_chroot.sh

Run Steam


Save the steam file from this gist as ~/.local/bin/steam, then chmod +x ~/.local/bin/steam. This will be how you run Steam.


type steam to run


Note: If you get an error like this, just try again. It should work after a few tries.

    dlmopen steamui.so failed: steamui.so: cannot open shared object file: No such file or directory Failed to load steamui.so - dlerror(): (null

Save the steam.desktop file from this gist as ~/.local/share/applications/steam.desktop. It creates an entry for Steam in your app launcher. (It will launch with the terminal, because Steam is quite slow to launch, so you would want to know what's going on, and it might crash and restart, etc.)


Troubleshooting Steam


Check the Steam logs in ~/.steam/root/logs

Workaround for transparent Steam window


Workaround has already been added in the steam file from this gist (~/.local/bin/steam).

The old workaround (disabling GPU accelerated rendering) was found to be bad, as it caused the renderer process to keep crashing (also, it was just slow).

If you have previously disabled GPU accelerated rendering, you should remove this line from ~/.steam/registry.vdf:

"GPUAccelWebViewsV3" "0"

Workaround for Steam menus not working properly

Switch to Big Picture Mode. (Please make sure you don't have GPU accelerated rendering disabled, or it'd be really slow.)

steam

#!/bin/sh
force_args='-cef-force-occlusion -cef-force-opaque-backgrounds'
if [ "$(cut -d '' -f1 < /proc/1/cmdline)" = '/init.krun' ]; then
exec '/usr/bin/FEXInterpreter' '/usr/bin/steam' ${force_args} "$@"
fi
if [ -z "${DBX_CONTAINER_MANAGER}" ]; then
export DBX_CONTAINER_MANAGER=podman
fi
if [ -n "${CONTAINER_ID}" ]; then
container_name="${CONTAINER_ID}"
# if the variable is not set, let's fall back to some tricks.
elif [ -e /.dockerenv ]; then
# we're in docker, let's use this trick
container_name=$(grep "memory:/" < /proc/self/cgroup | sed 's|.*/||')
elif [ -e /run/.containerenv ]; then
# we're in podman or lilipod, use this other trick
container_name=$(grep "name=" /run/.containerenv | cut -d'=' -f2- | tr -d '"')
fi
if [ -z "${container_name}" ]; then
exec "/usr/bin/distrobox-enter" -n asahi-krun -- krun '/usr/bin/FEXInterpreter' '/usr/bin/steam' ${force_args} "$@"
elif [ -n "${container_name}" ] && [ "${container_name}" != "asahi-krun" ]; then
exec distrobox-host-exec "$HOME/.local/bin/steam" "$@"
else
exec krun '/usr/bin/FEXInterpreter' '/usr/bin/steam' ${force_args} "$@"
fi
steam.desktop

[Desktop Entry]
Name=Steam
Comment=Application for managing and playing games on Steam
Comment[pt_BR]=Aplicativo para jogar e gerenciar jogos no Steam
Comment[bg]=Приложение за ръководене и пускане на игри в Steam
Comment[cs]=Aplikace pro spravování a hraní her ve službě Steam
Comment[da]=Applikation til at håndtere og spille spil på Steam
Comment[nl]=Applicatie voor het beheer en het spelen van games op Steam
Comment[fi]=Steamin pelien hallintaan ja pelaamiseen tarkoitettu sovellus
Comment[fr]=Application de gestion et d'utilisation des jeux sur Steam
Comment[de]=Anwendung zum Verwalten und Spielen von Spielen auf Steam
Comment[el]=Εφαρμογή διαχείρισης παιχνιδιών στο Steam
Comment[hu]=Alkalmazás a Steames játékok futtatásához és kezeléséhez
Comment[it]=Applicazione per la gestione e l'esecuzione di giochi su Steam
Comment[ja]=Steam 上でゲームを管理&プレイするためのアプリケーション
Comment[ko]=Steam에 있는 게임을 관리하고 플레이할 수 있는 응용 프로그램
Comment[no]=Program for å administrere og spille spill på Steam
Comment[pt_PT]=Aplicação para organizar e executar jogos no Steam
Comment[pl]=Aplikacja do zarządzania i uruchamiania gier na platformie Steam
Comment[ro]=Aplicație pentru administrarea și jucatul jocurilor pe Steam
Comment[ru]=Приложение для игр и управления играми в Steam
Comment[es]=Aplicación para administrar y ejecutar juegos en Steam
Comment[sv]=Ett program för att hantera samt spela spel på Steam
Comment[zh_CN]=管理和进行 Steam 游戏的应用程序
Comment[zh_TW]=管理並執行 Steam 遊戲的應用程式
Comment[th]=โปรแกรมสำหรับจัดการและเล่นเกมบน Steam
Comment[tr]=Steam üzerinden oyun oynama ve düzenleme uygulaması
Comment[uk]=Програма для керування іграми та запуску ігор у Steam
Comment[vi]=Ứng dụng để quản lý và chơi trò chơi trên Steam
Exec=steam %U
Icon=steam
Terminal=true
Type=Application
Categories=Network;FileTransfer;Game;
MimeType=x-scheme-handler/steam;x-scheme-handler/steamlink;
Actions=Store;Community;Library;Servers;Screenshots;News;Settings;BigPicture;Friends;
PrefersNonDefaultGPU=true
X-KDE-RunOnDiscreteGpu=true
[Desktop Action Store]
Name=Store
Name[pt_BR]=Loja
Name[bg]=Магазин
Name[cs]=Obchod
Name[da]=Butik
Name[nl]=Winkel
Name[fi]=Kauppa
Name[fr]=Magasin
Name[de]=Shop
Name[el]=ΚΑΤΑΣΤΗΜΑ
Name[hu]=Áruház
Name[it]=Negozio
Name[ja]=ストア
Name[ko]=상점
Name[no]=Butikk
Name[pt_PT]=Loja
Name[pl]=Sklep
Name[ro]=Magazin
Name[ru]=Магазин
Name[es]=Tienda
Name[sv]=Butik
Name[zh_CN]=商店
Name[zh_TW]=商店
Name[th]=ร้านค้า
Name[tr]=Mağaza
Name[uk]=Крамниця
Name[vi]=Cửa hàng
Exec=steam steam://store
[Desktop Action Community]
Name=Community
Name[pt_BR]=Comunidade
Name[bg]=Общност
Name[cs]=Komunita
Name[da]=Fællesskab
Name[nl]=Community
Name[fi]=Yhteisö
Name[fr]=Communauté
Name[de]=Community
Name[el]=Κοινότητα
Name[hu]=Közösség
Name[it]=Comunità
Name[ja]=コミュニティ
Name[ko]=커뮤니티
Name[no]=Samfunn
Name[pt_PT]=Comunidade
Name[pl]=Społeczność
Name[ro]=Comunitate
Name[ru]=Сообщество
Name[es]=Comunidad
Name[sv]=Gemenskap
Name[zh_CN]=社区
Name[zh_TW]=社群
Name[th]=ชุมชน
Name[tr]=Topluluk
Name[uk]=Спільнота
Name[vi]=Cộng đồng
Exec=steam steam://url/SteamIDControlPage
[Desktop Action Library]
Name=Library
Name[pt_BR]=Biblioteca
Name[bg]=Библиотека
Name[cs]=Knihovna
Name[da]=Bibliotek
Name[nl]=Bibliotheek
Name[fi]=Kokoelma
Name[fr]=Bibliothèque
Name[de]=Bibliothek
Name[el]=Συλλογή
Name[hu]=Könyvtár
Name[it]=Libreria
Name[ja]=ライブラリ
Name[ko]=라이브러리
Name[no]=Bibliotek
Name[pt_PT]=Biblioteca
Name[pl]=Biblioteka
Name[ro]=Colecţie
Name[ru]=Библиотека
Name[es]=Biblioteca
Name[sv]=Bibliotek
Name[zh_CN]=库
Name[zh_TW]=收藏庫
Name[th]=คลัง
Name[tr]=Kütüphane
Name[uk]=Бібліотека
Name[vi]=Thư viện
Exec=steam steam://open/games
[Desktop Action Servers]
Name=Servers
Name[pt_BR]=Servidores
Name[bg]=Сървъри
Name[cs]=Servery
Name[da]=Servere
Name[nl]=Servers
Name[fi]=Palvelimet
Name[fr]=Serveurs
Name[de]=Server
Name[el]=Διακομιστές
Name[hu]=Szerverek
Name[it]=Server
Name[ja]=サーバー
Name[ko]=서버
Name[no]=Tjenere
Name[pt_PT]=Servidores
Name[pl]=Serwery
Name[ro]=Servere
Name[ru]=Серверы
Name[es]=Servidores
Name[sv]=Servrar
Name[zh_CN]=服务器
Name[zh_TW]=伺服器
Name[th]=เซิร์ฟเวอร์
Name[tr]=Sunucular
Name[uk]=Сервери
Name[vi]=Máy chủ
Exec=steam steam://open/servers
[Desktop Action Screenshots]
Name=Screenshots
Name[pt_BR]=Capturas de tela
Name[bg]=Снимки
Name[cs]=Snímky obrazovky
Name[da]=Skærmbilleder
Name[nl]=Screenshots
Name[fi]=Kuvankaappaukset
Name[fr]=Captures d'écran
Name[de]=Screenshots
Name[el]=Φωτογραφίες
Name[hu]=Képernyőmentések
Name[it]=Screenshot
Name[ja]=スクリーンショット
Name[ko]=스크린샷
Name[no]=Skjermbilder
Name[pt_PT]=Capturas de ecrã
Name[pl]=Zrzuty ekranu
Name[ro]=Capturi de ecran
Name[ru]=Скриншоты
Name[es]=Capturas
Name[sv]=Skärmdumpar
Name[zh_CN]=截图
Name[zh_TW]=螢幕擷圖
Name[th]=ภาพหน้าจอ
Name[tr]=Ekran Görüntüleri
Name[uk]=Скріншоти
Name[vi]=Ảnh chụp
Exec=steam steam://open/screenshots
[Desktop Action News]
Name=News
Name[pt_BR]=Notícias
Name[bg]=Новини
Name[cs]=Zprávy
Name[da]=Nyheder
Name[nl]=Nieuws
Name[fi]=Uutiset
Name[fr]=Actualités
Name[de]=Neuigkeiten
Name[el]=Νέα
Name[hu]=Hírek
Name[it]=Notizie
Name[ja]=ニュース
Name[ko]=뉴스
Name[no]=Nyheter
Name[pt_PT]=Novidades
Name[pl]=Aktualności
Name[ro]=Știri
Name[ru]=Новости
Name[es]=Noticias
Name[sv]=Nyheter
Name[zh_CN]=新闻
Name[zh_TW]=新聞
Name[th]=ข่าวสาร
Name[tr]=Haberler
Name[uk]=Новини
Name[vi]=Tin tức
Exec=steam steam://open/news
[Desktop Action Settings]
Name=Settings
Name[pt_BR]=Configurações
Name[bg]=Настройки
Name[cs]=Nastavení
Name[da]=Indstillinger
Name[nl]=Instellingen
Name[fi]=Asetukset
Name[fr]=Paramètres
Name[de]=Einstellungen
Name[el]=Ρυθμίσεις
Name[hu]=Beállítások
Name[it]=Impostazioni
Name[ja]=設定
Name[ko]=설정
Name[no]=Innstillinger
Name[pt_PT]=Definições
Name[pl]=Ustawienia
Name[ro]=Setări
Name[ru]=Настройки
Name[es]=Parámetros
Name[sv]=Inställningar
Name[zh_CN]=设置
Name[zh_TW]=設定
Name[th]=การตั้งค่า
Name[tr]=Ayarlar
Name[uk]=Налаштування
Name[vi]=Thiết lập
Exec=steam steam://open/settings
[Desktop Action BigPicture]
Name=Big Picture
Exec=steam steam://open/bigpicture
[Desktop Action Friends]
Name=Friends
Name[pt_BR]=Amigos
Name[bg]=Приятели
Name[cs]=Přátelé
Name[da]=Venner
Name[nl]=Vrienden
Name[fi]=Kaverit
Name[fr]=Amis
Name[de]=Freunde
Name[el]=Φίλοι
Name[hu]=Barátok
Name[it]=Amici
Name[ja]=フレンド
Name[ko]=친구
Name[no]=Venner
Name[pt_PT]=Amigos
Name[pl]=Znajomi
Name[ro]=Prieteni
Name[ru]=Друзья
Name[es]=Amigos
Name[sv]=Vänner
Name[zh_CN]=好友
Name[zh_TW]=好友
Name[th]=เพื่อน
Name[tr]=Arkadaşlar
Name[uk]=Друзі
Name[vi]=Bạn bè
Exec=steam steam://open/friends


Reference:
Asahi Linux
https://github.com/teohhanhui

My Github
https://github.com/ycechungAI

No comments:

Post a Comment

Xbox Kernel Code Execution in SystemOS POC Explained 2024/06

 In the Xbox wiki  code execution via Game Script UWP App, it is available currently in Microsoft store which allows the writing and executi...