Skip to content

Instantly share code, notes, and snippets.

@ctsrc
Forked from niw/README.en.md
Last active October 9, 2025 20:37
Show Gist options
  • Save ctsrc/a1f57933a2cde9abc0f07be12889f97f to your computer and use it in GitHub Desktop.
Save ctsrc/a1f57933a2cde9abc0f07be12889f97f to your computer and use it in GitHub Desktop.
Guide: Run FreeBSD 13.1-RELEASE for ARM64 in QEMU on Apple Silicon Mac (MacBook Pro M1, etc) with HVF acceleration (Hypervisor.framework)

ARM 版 Windows 10 や Ubuntu for ARM64 を Apple Silicon な Mac で動かす

ARM 版 Windows 10 や Ubuntu を Apple Silicon な Mac で動かす簡単な方法です。

メモ: 2020年12月19日現時点での方法で、今後おおきく改善されていくと思います(だといいな。)

ARM 版 Windows 10 を動かす

  1. Xcode を App Store で、あるいは Command Line Tools を Apple Silicon な Mac にインストール

    xcode-select --install
    
  2. MacPorts で QEMU の依存ライブラリをインストール

    https://www.macports.org/install.php

    sudo port install ninja pkgconfig glib2 libpixman
    
  3. QEMU のソースコードをとってくる

    git clone https://git.qemu.org/git/qemu.git
    
  4. ローカルブランチを作って、@_AlexGraf氏がつくった Hypervisor.framework のパッチをあてる

    cd qemu
    git checkout master -b wip/hvf
    curl 'https://patchwork.kernel.org/series/400619/mbox/'|git am
    
  5. QEMU をビルドする

    必ず PATHPKG_CONFIG_PATH を書き換えるなどして、Homebrew などの x86_64 のツールがインストールされていないか、有効になっていないことを確認してください

    mkdir build
    cd build
    ../configure --target-list=aarch64-softmmu --enable-cocoa
    make -j
    
  6. QEMU 用の EDK II OVMF EFI イメージをダウンロードする。

    このイメージは stable202011 タグに、QemuRamfb.c に追加の解像度を足したものです。

    https://gist.github.com/niw/4f1f9bb572f40d406866f23b3127919b/raw/f546faea68f4149c06cca88fa67ace07a3758268/QEMU_EFI-cb438b9-edk2-stable202011-with-extra-resolutions.tar.gz

    さらに解像度を追加するなど、ソースコードからビルドする場合は以下を参照のこと。

  7. pflash イメージを作って、画面サイズなどを設定する不揮発なストレージを準備する

    QEMU_EFI-....tar.gz をダウンロードしたディレクトリで以下を実行。

    cd ~/Downloads
    tar xzvf QEMU_EFI-*.tar.gz
    dd if=/dev/zero of=pflash0.img bs=1m count=64
    dd if=/dev/zero of=pflash1.img bs=1m count=64
    dd if=QEMU_EFI.fd of=pflash0.img conv=notrunc
    dd if=QEMU_VARS.fd of=pflash1.img conv=notrunc
    
    • このステップは省略可能。その場合は次のステップで -drive ...,if=pflash,... のかわりに -bios ~/Downloads/QEMU_EFI.fd を指定すること。ただし、EFI での変更が保存されなくなります。
  8. Windows 10 on ARM Insider Preview をダウンロードする

    https://www.microsoft.com/en-us/software-download/windowsinsiderpreviewARM64

  9. VHDX から qcow2 に変換する

    VHDX のままだとかなりの頻度でイメージが壊れる印象があるので qcow2 に変換しておく。

    qemu-img convert -p -O qcow2 ~/Downloads/Windows10_InsiderPreview_Client_ARM64_en-us_20231.VHDX ~/Downloads/Windows10_InsiderPreview_Client_ARM64_en-us_20231.qcow2
    
  10. Windows 10 を起動する

    ./qemu-system-aarch64 \
      -monitor stdio \
      -M virt,highmem=off \
      -accel hvf \
      -cpu cortex-a72 \
      -smp 4 \
      -m 4096 \
      -drive file=~/Downloads/pflash0.img,format=raw,if=pflash,readonly=on \
      -drive file=~/Downloads/pflash1.img,format=raw,if=pflash \
      -device ramfb \
      -device qemu-xhci \
      -device usb-kbd \
      -device usb-tablet \
      -device intel-hda \
      -device hda-duplex \
      -nic user,model=virtio \
      -drive file=~/Downloads/Windows10_InsiderPreview_Client_ARM64_en-us_20231.qcow2,format=qcow2,if=none,id=boot,cache=writethrough \
      -device nvme,drive=boot,serial=boot
    
    • イメージへのパスなどは適宜修正してください。
    • TianoCore のロゴが出ている時に ESC を押して、Device ManagerOVMF Platform ConfigurationChange Preferred Resolution for Next Boot と進めて解像度を変更できます。
    • 解像度を追加するには、下記の「EDK II の OVMF EFI イメージをビルドする」に従って OvmfPkg/QemuRamfbDxe/QemuRamfb.c を変更し、新しい QEMU_EFI.fd を作ってください。
    • -device usb-mouse より -device usb-tablet を使うことでマウスカーソルがロックされなくなり使いやすくなります。
    • -device intel-hda -device hda-duplex でオーディオが使えるようになります。
    • -nic user,model=virtio がネットワークインターフェイスです。有効にするには以下を参照してください。

インターネットに接続する

VirtIO NIC は標準では有効にならないので、デバイスドライバを入れる必要がある。

  1. VirtIO デバイスドライバの ISO を Fedora Project からダウンロード。

    https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.190-1/virtio-win-0.1.190.iso

  2. デバイスドライバの ISO をマウント

    qemu-system-aarch64 のオプションに以下を追加する。

    -drive file=~/Downloads/virtio-win-0.1.190.iso,media=cdrom,if=none,id=drivers \
    -device usb-storage,drive=drivers
    

    イメージへのパスなどは適宜修正してください。

  3. デバイスドライバの署名検証を無効にする

    Windows を起動して Windows スタートボタン を右クリック、Command Prompt (Admin) を選択。

    bcdedit を使ってテスト署名されたデバイスドライバを有効にする。

    bcdedit.exe -set TESTSIGNING ON
    

    このあと Windows を再起動すること。

    詳細はこちらを参照のこと。

  4. デバイスドライバのインストール

    Windows が再度起動したら Windows スタートボタン を右クリック、Device Manager を選択。

    Device Manager のウィンドウで、View メニューの Devices by Connection を選択。

    デバイスのツリーから、ACPU ARM64-based PCMicrosoft ACPI-Compliant SystemPCI Express Root Complex と選択してその中にある Unknown device を探す。 (Unknown device はデバイスのツリーに沢山あるけれど、PCI Express Root Complexの下にあるのが、VirtIO NIC。)

    該当の Unknown device を右クリックして、Update Drivers を選択、Browse my computer for drivers を選んで、D:\NetKVM\w10\ARM64 を指定。

    Next をクリックして Red Hat VertIO Ethernet Adapter をインストール。

Ubuntu Server for ARM64 を動かす

ARM 版 Windows 10 を動かす手順に従って QEMU を準備して、Ubuntu Server for ARM64 をダウンロードしてインストールします。

  1. 上記の手順 1 から 7 までに従って QEMU を準備する。

  2. 空のディスクイメージを作成する。

    ./qemu-img create -f qcow2 ~/Downloads/ubuntu.qcow2 40G 
    
  3. Ubuntu Server for ARM64 をダウンロードする。

    https://ubuntu.com/download/server/arm

  4. Ubuntu Server for ARM をインストールする。

    ./qemu-system-aarch64 \
      -monitor stdio \
      -M virt,highmem=off \
      -accel hvf \
      -cpu cortex-a72 \
      -smp 4 \
      -m 4096 \
      -drive file=~/Downloads/pflash0.img,format=raw,if=pflash,readonly=on \
      -drive file=~/Downloads/pflash1.img,format=raw,if=pflash \
      -device virtio-gpu-pci \
      -display default,show-cursor=on \
      -device qemu-xhci \
      -device usb-kbd \
      -device usb-tablet \
      -device intel-hda \
      -device hda-duplex \
      -drive file=~/Downloads/ubuntu.qcow2,if=virtio,cache=writethrough \
      -cdrom ~/Downloads/ubuntu-20.04.1-live-server-arm64.iso
    
    • 指示に従ってインストールしたあとは -cdrom は不要です。

EDK II の OVMF EFI イメージをビルドする

上記の手順に従って Ubuntu Server for ARM64 を動かします。

  1. EDK II のソースコードを取ってくる。

    git clone --depth 1 --branch edk2-stable202011 https://github.com/tianocore/edk2.git
    cd edk2
    git submodule update --init --recursive
    

    Hypervisor.framework パッチの制限で xHCI を無効にする必要があれば /ArmVirtPkg/ArmVirtQemu.dsc/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc にある MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf の行をコメントアウト。たぶん現状は問題ない。

  2. ビルドする

    sudo apt install iasl python3 python3-distutils uuid-dev make g++
    source edksetup.sh
    make -C BaseTools
    build -a AARCH64 -t GCC5 -p ArmVirtPkg/ArmVirtQemu.dsc
    

    Build/ArmVirtQemu-AARCH64/DEBUG_GCC5/FVQEMU_EFI.fdQEMU_VARS.fd ができるはず。

    • これらのファイルを簡単に macOS ホストに取り出すには macOS でリモートアクセスを有効にして scp10.0.2.2 にコピー。

    • x86_64 の環境でビルドする場合は以下のツールチェーンでクロスコンパイル。

      sudo apt install gcc-aarch64-linux-gnu
      env GCC5_AARCH64_PREFIX=aarch64-linux-gnu- build -a AARCH64 -t GCC5 -p ArmVirtPkg/ArmVirtQemu.dsc
      

How to run Windows 10 on ARM or Ubuntu for ARM64 in QEMU on Apple Silicon Mac

Here is easy steps to try Windows 10 on ARM or Ubuntu for ARM64 on your Apple Silicon Mac. Enjoy!

NOTE: that this is current, 12/19/2020 state. It will be improved a lot in upcoming a few months... (I hope.)

Running Windows 10 on ARM

  1. Install Xcode from App Store or install Command Line Tools on your Mac running on Apple Silicon.

    xcode-select --install
    
  2. Install MacPorts and QEMU dependencies.

    https://www.macports.org/install.php

    sudo port install ninja pkgconfig glib2 libpixman
    
  3. Clone QEMU source code.

    git clone https://git.qemu.org/git/qemu.git
    
  4. Create a local branch then apply Hypervisor.framework patches that @_AlexGraf made.

    cd qemu
    git checkout master -b wip/hvf
    curl 'https://patchwork.kernel.org/series/400619/mbox/'|git am
    
  5. Build QEMU

    Before building, please ensure there are no x86_64 tools enabled, such the one installed by Homebrew, by rewriting PATH or PKG_CONFIG_PATH.

    mkdir build
    cd build
    ../configure --target-list=aarch64-softmmu --enable-cocoa
    make -j
    
  6. Download pre-build EDK II OVMF EFI image for QEMU.

    This EFI image is built from stable202011 tag with additional resolutions in QemuRamfb.c.

    https://gist.github.com/niw/4f1f9bb572f40d406866f23b3127919b/raw/f546faea68f4149c06cca88fa67ace07a3758268/QEMU_EFI-cb438b9-edk2-stable202011-with-extra-resolutions.tar.gz

    To build it from the source code for adding more resolutions, see the following section.

  7. Prepare pflash for non-volatile variable store, such as screen resolution.

    In the directory where you downloaded QEMU_EFI-....tar.gz, run following commands.

    cd ~/Downloads
    tar xzvf QEMU_EFI-*.tar.gz
    dd if=/dev/zero of=pflash0.img bs=1m count=64
    dd if=/dev/zero of=pflash1.img bs=1m count=64
    dd if=QEMU_EFI.fd of=pflash0.img conv=notrunc
    dd if=QEMU_VARS.fd of=pflash1.img conv=notrunc
    
    • This step is optional, you can use -bios ~/Downloads/QEMU_EFI.fd instead of -drive ...if=pflash lines in the next step, but in that case, any changes in EFI will not be persistent.
  8. Download Windows 10 on ARM Insider Preview

    https://www.microsoft.com/en-us/software-download/windowsinsiderpreviewARM64

  9. Convert VHDX downloaded Windows image to qcow2 format

    It seems that VHDX often gets broken while it is being used, so probably it is better to convert it to qcow2 format before using it.

    qemu-img convert -p -O qcow2 ~/Downloads/Windows10_InsiderPreview_Client_ARM64_en-us_20231.VHDX ~/Downloads/Windows10_InsiderPreview_Client_ARM64_en-us_20231.qcow2
    
  10. Run Windows 10

    ./qemu-system-aarch64 \
      -monitor stdio \
      -M virt,highmem=off \
      -accel hvf \
      -cpu cortex-a72 \
      -smp 4 \
      -m 4096 \
      -drive file=~/Downloads/pflash0.img,format=raw,if=pflash,readonly=on \
      -drive file=~/Downloads/pflash1.img,format=raw,if=pflash \
      -device ramfb \
      -device qemu-xhci \
      -device usb-kbd \
      -device usb-tablet \
      -device intel-hda \
      -device hda-duplex \
      -drive file=~/Downloads/Windows10_InsiderPreview_Client_ARM64_en-us_20231.qcow2,format=qcow2,if=none,id=boot,cache=writethrough \
      -device nvme,drive=boot,serial=boot
    
    • Please modify each path to the image depends on your environment.
    • Hit ESC while you see TianoCore, then Device Manager, OVMF Platform Configuration, Change Preferred Resolution for Next Boot to change screen resolution.
    • To add more resolutions, follow "Build EDK II OVMF EFI image from the source code" below and modify OvmfPkg/QemuRamfbDxe/QemuRamfb.c then build new QEMU_EFI.fd.
    • Use -device usb-tablet instead of -device usb-mouse allows transparently moving mouse cursor.
    • -device intel-hda -device hda-duplex to enable audio.
    • -nic user,model=virtio is the network interface. To enable it, see the following section.

Enable the internet

VirtIO NIC is not enabled by default. To make it works, you need to

device driver.

  1. Download VirtIO device drivers ISO from Fedora Project.

    https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.190-1/virtio-win-0.1.190.iso

  2. Mount device drivers ISO

    Add next options to qemu-system-aarch64.

    -drive file=~/Downloads/virtio-win-0.1.190.iso,media=cdrom,if=none,id=drivers \
    -device usb-storage,drive=drivers
    

    Please modify each path to the image depends on your environment.

  3. Disable device driver signature enforcement

    Boot Windows, then right click Windows Start button, then select Command Prompt (Admin).

    Use bcdedit to enable test-signed device drivers.

    bcdedit.exe -set TESTSIGNING ON
    

    Then reboot Windows.

    See here for the details.

  4. Install driver

    Once Windows booted again, then right click Windows Start button, then select Device Manager.

    In Device Manager, select View menu then Devices by Connection.

    Navigate in the device tree, select ACPU ARM64-based PC, Microsoft ACPI-Compliant System, PCI Express Root Complex, then you will see one Unknown device there. (There are many Unknown device in tree but the one under PCI Express Root Complex is the VirtIO NIC.)

    Right click Unknown device then select Update Drivers, then Browse my computer for drivers, then select D:\NetKVM\w10\ARM64.

    Click Next to install Red Hat VertIO Ethernet Adapter.

Running Ubuntu Server for ARM64

Follow the same steps for Windows 10 to prepare QEMU, then download Ubuntu Server for ARM64 and install it.

  1. Follow previous steps from 1. to 7. to prepare QEMU.

  2. Create an empty disk image.

    ./qemu-img create -f qcow2 ~/Downloads/ubuntu.qcow2 40G 
    
  3. Download Ubuntu Server for ARM64

    https://ubuntu.com/download/server/arm

  4. Install Ubuntu Server for ARM

    ./qemu-system-aarch64 \
      -monitor stdio \
      -M virt,highmem=off \
      -accel hvf \
      -cpu cortex-a72 \
      -smp 4 \
      -m 4096 \
      -drive file=~/Downloads/pflash0.img,format=raw,if=pflash,readonly=on \
      -drive file=~/Downloads/pflash1.img,format=raw,if=pflash \
      -device virtio-gpu-pci \
      -display default,show-cursor=on \
      -device qemu-xhci \
      -device usb-kbd \
      -device usb-tablet \
      -device intel-hda \
      -device hda-duplex \
      -drive file=~/Downloads/ubuntu.qcow2,if=virtio,cache=writethrough \
      -cdrom ~/Downloads/ubuntu-20.04.1-live-server-arm64.iso
    
    • Follow instruction to install Ubuntu Server. Once it's installed, -cdrom argument is not needed.

Build EDK II OVMF EFI image from the source code

Follow the previous instructions to run Ubuntu Server for ARM64.

  1. Checkout EDK II source code.

    git clone --depth 1 --branch edk2-stable202011 https://github.com/tianocore/edk2.git
    cd edk2
    git submodule update --init --recursive
    

    You may want to disable xHCI due to current Hypervisor.framework patch limitation. Comment out MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf in /ArmVirtPkg/ArmVirtQemu.dsc and /ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc. Probably this is no longer needed.

  2. Build it.

    sudo apt install iasl python3 python3-distutils uuid-dev make g++
    source edksetup.sh
    make -C BaseTools
    build -a AARCH64 -t GCC5 -p ArmVirtPkg/ArmVirtQemu.dsc
    

    Then, you will get QEMU_EFI.fd and QEMU_VARS.fd in Build/ArmVirtQemu-AARCH64/DEBUG_GCC5/FV.

    • The easiest way to take these files to the host macOS, run Remove Login on macOS then scp these to 10.0.2.2.

    • To build these on x86_64 environment, use following toolchain to cross compile.

      sudo apt install gcc-aarch64-linux-gnu
      env GCC5_AARCH64_PREFIX=aarch64-linux-gnu- build -a AARCH64 -t GCC5 -p ArmVirtPkg/ArmVirtQemu.dsc
      
@BrettDong
Copy link

DNS is working but ping gives weird result:
螢幕截圖 2021-02-11 下午4 52 46

@BrettDong
Copy link

@felipedbene
Copy link

I have one of these running in a actual nano pi r2s but the problem is that they only way I can reach it is using ssh but i dunno the image's default user and password, does anybody know it, by any chance?

@BrettDong
Copy link

Username is root and there is no password.

@BrettDong
Copy link

Good news for everyone! There is some update in https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=237441 regarding the network issue:

It appears this is a libslirp issue on macOS.
Rebuilding QEMU with slirp updated to include https://gitlab.freedesktop.org/slirp/libslirp/-/commit/7271345efe182199acaeae602cb78a94a7c6dc9d fixes this issue for me.
See also https://gitlab.freedesktop.org/slirp/libslirp/-/issues/35
I've filed Homebrew/homebrew-core#73517

@ctsrc
Copy link
Author

ctsrc commented Sep 20, 2021

@BrettDong

I've filed Homebrew/homebrew-core#73517

I tried to build qemu with the most recent hvf patches now and at the same time specifying --enable-slirp=system when running configure.

But I am still getting the same kind of errors inside of the FreeBSD VM when I try to ping 1.1.1.1.

Is there something else one needed to do in order to fix this issue that I missed? My homebrew installed libslirp is version 4.6.1 so it should have the patch.

@sneak
Copy link

sneak commented Aug 4, 2022

Funnily enough, this tutorial uses the linux-style dd numeric syntax (lowercase M) which fails on macOS (I think it inherited dd from freebsd a looong time ago) and needs bs=1M (not bs=1m).

Running the commands as-is on current macOS results in:

dd: invalid number: ‘1m’
dd: invalid number: ‘1m’

@ctsrc
Copy link
Author

ctsrc commented Aug 4, 2022

@sneak What version of macOS are you running? The dd commands given in the guide run as they should on macOS Monterey Version 12.5

Also, what is the output for you of the following?

which dd

You should get the following output:

/bin/dd

If you are getting a different output, and you are using the same version of macOS that I mentioned, then you are not using the dd that ships with macOS. In which case, make sure you are using the dd that ships with macOS.

@dmilith
Copy link

dmilith commented Aug 4, 2022

This guide will not work on M1 macs. Qemu 7.0 has a regression (6.2 worked just fine) and you have to use another build:

# Install QEmu for Mac M1:
#
brew tap uenob/qemu-hvf
brew install --head qemu-hvf

# and then you may want to start headless vm like this:

/opt/homebrew/opt/qemu-hvf/bin/qemu-system-aarch64 \
    -M virt,accel=hvf,highmem=off \
    -m 12288 \
    -smp cores=4 \
    -cpu cortex-a72 \
    -drive file=edk2-aarch64-code.fd,if=pflash,format=raw,readonly=on \
    -drive file=freebsd13.qcow2,format=qcow2 \
    -nographic \
    -device virtio-net-device,netdev=en0 \
    -netdev user,id=en0,hostfwd=tcp::4445-:22 \
    -serial tcp::4444,server,telnet,nowait \
    -pidfile freebsd13.pid

@ctsrc
Copy link
Author

ctsrc commented Aug 5, 2022

@dmilith What do you mean it won't work? I am running qemu 7.0 as shown in the output of the guide, running on MacBook Pro (13-inch, M1, 2020).

I see that you are using the highmem=off argument. With qemu 7.0 you must run without that part.

Please install qemu 7.0 and follow the guide step by step and you will see that it does work.

@astreknet
Copy link

astreknet commented Aug 19, 2022

Tested on MacBook Air M2, works fine.
I just tested OpenBSD too:
https://gist.github.com/astreknet/4860e3362ad98e1116f0a970b99e2afc

@superbonaci
Copy link

This guide will not work on M1 macs. Qemu 7.0 has a regression (6.2 worked just fine) and you have to use another build:

# Install QEmu for Mac M1:
#
brew tap uenob/qemu-hvf
brew install --head qemu-hvf

# and then you may want to start headless vm like this:

/opt/homebrew/opt/qemu-hvf/bin/qemu-system-aarch64 \
    -M virt,accel=hvf,highmem=off \
    -m 12288 \
    -smp cores=4 \
    -cpu cortex-a72 \
    -drive file=edk2-aarch64-code.fd,if=pflash,format=raw,readonly=on \
    -drive file=freebsd13.qcow2,format=qcow2 \
    -nographic \
    -device virtio-net-device,netdev=en0 \
    -netdev user,id=en0,hostfwd=tcp::4445-:22 \
    -serial tcp::4444,server,telnet,nowait \
    -pidfile freebsd13.pid

With QEMU 7.2 it works perfectly fine but probably it's a bit outdated.

@ysmolski
Copy link

ysmolski commented Apr 1, 2023

Ran exactly like explained in the guide, but only on qemu 7.2. While idle, FreeBSD creates load ~200% CPU on my host machine. Is it supposed to be like this?

Update:
I found a solution - simply add this line: kern.hz=100 in /boot/loader.conf
Source: https://gitlab.com/qemu-project/qemu/-/issues/959

@superbonaci
Copy link

Ran exactly like explained in the guide, but only on qemu 7.2. While idle, FreeBSD creates load ~200% CPU on my host machine. Is it supposed to be like this?

Update: I found a solution - simply add this line: kern.hz=100 in /boot/loader.conf Source: https://gitlab.com/qemu-project/qemu/-/issues/959

That's inside FreeBSD root filesystems isn't it?

@ysmolski
Copy link

ysmolski commented Apr 6, 2023

That's inside FreeBSD root filesystems isn't it?

Yes, on the guest machine (inside qemu) that runs FreeBSD. So this is a boot file config for the guest FreeBSD.

@bsdimp
Copy link

bsdimp commented Dec 17, 2023

For some reason, I had to do
root@freebsd:~ # efibootmgr -a -c -l /boot/efi/EFI/BOOT/bootaa64.efi -L FreeBSD-14
to get a boot entry for FreeBSD. Not sure why this wasn't the default after the first boot...

@ylluminate
Copy link

Has anyone gotten X running with or without acceleration?

@cormega2000
Copy link

On a M1 Mac with 14.1 absolut perfect

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment