Aug 2018 [EN||]

Ryzen 移動平臺上安裝 Gentoo Linux

Linux 內核對於跟進支持 Ryzen 移動低壓 CPU 的熱情似乎和市面上寥寥無幾的 Ryzen 筆記本熱度十分吻合。雖然從 Linux 4.11 起就對 Ryzen 桌面 CPU 有較好的支持,但是 4.17 以下的內核在其移動 CPU 上甚至無法正常載入。撰寫本文時(2018.07),絕大多數發行版本的默認內核版本皆 < 4.17,所以存在的幾個激進的 Linux 發行版本是我僅有的選擇,Gentoo 便是其一。

翻閱了相較之前更為友善的 Gentoo Handbook 再加之這回有了一定折騰必要性。使用 Gentoo 的興致就這麼(又)被點燃了 😂,於是有了記錄幾個安裝要點的本文。

使用 Arch Linux 安裝鏡像

Gentoo 官方提供的滾動更新的安裝鏡像匪夷地不支援 UEFI 啟動 (2018.07)。它的確提供了一個產於 2016 年的支援 UEFI 啟動的鏡像。不過我清楚這個鏡像在我的設備上一定無法正常載入,所以使用最新內核的 Arch 鏡像似乎是最好的選擇。

更新: Gentoo Handbook 的內容現在已經被更新。「As of August 23, 2018 the official Minimal CDs are capable of booting in UEFI mode. Previous versions boot in BIOS (MBR) mode only. Readers looking to make their system UEFI bootable must download the latest ISO.」正如它所說的,最新的 ISO 已經支持 UEFI 啟動了。所以從現在開始,使用 Arch Linux 的安裝鏡像是不必要的了。

分區並準備使用 EFISTUB 引導

我的分區方案是遵從 Handbook 中的 Preparing the disks 章節,將 /root 分區掛載到 /mnt/gentoo 而後參考 EFI system partition 將 EFI 分區掛載到 /mnt/gentoo/esp,再將 /esp/EFI/Gentoo 掛載到 /mnt/gentoo/boot

這樣一來,在保持 ESP 分區的整潔的同時,內核檔被更新後也不需要手動更新 /boot 中的檔。屆時只需要使用老方法:把 /boot 下的一系列檔複製到 /esp/EFI/Gentoo 即可。

下載 Stage3 鏡像

瞭解網路配置部分內容可參閱 Network configuration

Handbook 中推薦使用 Links 訪問鏡像站下載 Stage3 的鏡像。Arch Linux 鏡像不自帶 Links,所以應該先使用 pacman 安裝 Lynx 或 Links 來完成這一操作。我的做法是在製作 Arch Linux 引導盤時,提前將下載好的 Stage3 鏡像複製到開機磁片中,然後複製到 /mnt/gentoo 目錄下。

修改預編譯參數

需要在 make.conf 中添加或更改某些參數以增加對 Ryzen 的支持。

其中在 CFLAGS-march 後添加 znver1 是 Ryzen CPU 必須修改的參數。如果設備使用 Vega 的 GPU,那麼應該加入 VIDEO_CARDS 參數 radeonsi。筆記本用戶應加入 Synaptics 的支援。除此之外,GENTOO_MIRRORS 選擇了速度十分可觀的吞拿魚 🐟,MAKEOPTS 參數遵循 CPU 核心數加一的原則,以 Ryzen 2700U 為例,即 -j5

以下是一個完整的 make.conf 的示例:

CFLAGS="-march=znver1 -O2 -pipe"
CXXFLAGS="${CFLAGS}"
MAKEOPTS="-j5"
VIDEO_CARDS="amdgpu radeonsi"
INPUT_DEVICES="evdev synaptics"
LANGUAS="zh_CN"
GENTOO_MIRRORS="https://mirrors.tuna.tsinghua.edu.cn/gentoo"

其它的參數可參考 Configuring compile options

Rsync Mirrors 的選擇

Gentoo 允許通過編輯 portage 倉庫的設定檔來指定 rsync 鏡像伺服器的地址。當然可以選擇吞拿魚或是 USTC 的源。

好奇心驅使我翻閱了 Gentoo 官方提供的 Gentoo rsync mirrors 頁面,然而並沒有找到來自中國大陸的鏡像站 (2018.07),或許因為現有的中國大陸不論是高校還是企業的鏡像站並沒有達到 Gentoo 的標準?可是臺灣同胞的源的速度又難以恭維。我無意中找到了由 KAIST 提供的 rsync 源。儘管只支持 IPv4,卻有著令人十分滿意的速度。這算是一個意外的發現吧。

恭喜清華喜托中國大陸唯一一個可用的 rsync mirror,現在這就是一個更好的選擇了。

關於 --make-rslave

Mounting the necessary filesystems 中提到啟用 Systemd 的支援需要 mount 後加入 --make-rslave 參數。mount 命令的 man page 表明這將遞迴地賦予目錄以 slave 的 propagation type,即目錄包括其下所有子目錄跟隨 master 變化,而自身變化時不通知 master 發生改變。

如果不使用 Systemd,也可以加入這個參數,這樣一來則不可以使用 umount -R 強行卸載分區。

選擇 Profile

使用 eselect 選擇 profile 的時候,需要注意觀察內核版本。對於 Gentoo 來說,撰寫本文時(2018.07)4.17 版本的 Linux 內核仍然是實驗性的內核,所以選項是在清單靠下方的位置。

如果和我一樣意圖最小化安裝 Gentoo,應該選擇附加安裝專案最少(也就是文字最短)的選項。特別是要避開帶有桌面環境的選項,即使在以後需要,也不建議將這項任務放置在安裝流程中,以免 CPU 短時間內的工作負擔過重。大家都不願意自己的筆記本親自把自己的手烹調成鐵板狗爪子。

USE Flags 的配置

USE Flags 是 Gentoo 的魅力所在,它提供了精簡化系統的可能性,説明保持系統的簡潔,最大化效率。但是其配置並不是一蹴而就的。我傾向於設置較少的全域 USE Flags,而針對每一個包設置局部的 USE Flags。

但這雖然是一個需要一定時日維護積累出來的成果,在一開始可以配置 -qt4 -qt5 -kde 來避免一些不必要的依賴。平日就要避免安裝軟體依賴於 Qt 等已經被禁止的 Flags。除此之外,Handbook 中 USE Flags 頁面是很好的深入瞭解管道。

手動編譯內核

選擇 genkernel 是一個比較無痛的編譯內核的方法,但這意味著內核就不能開啟 Ryzen 的相關參數了。保守的方式應該是 genkernel all 後再加入相關的內核參數並重新編譯一次內核。這種方式的缺點就是耗時和耗資源,編譯出來的內核並不小而美。

先通過 emerge linux-firmware 來安裝 AMD Zen 的微碼

emerge --ask sys-kernel/linux-firmware

別忘了安裝 AMD GPU 的相關驅動

emerge --ask x11-drivers/xf86-video-amdgpu

使用 menuconfig 開啟下面提及的幾個參數以提供對 Ryzen 和 AMD GPU 的支援,也開啟 EFISTUB 相關的內核選項。

Processor type and features --->
    [*] Symmetric multi-processing support
    [*] AMD ACPI2Platform devices support
    [*] /dev/cpu/microcode - microcode support
    [*] AMD microcode patch loading support
    [*] MTRR (Memory Type Range Register) support

    Processor family (Opteron/Athlon64/Hammer/K8) --->
        (X) Opteron/Athlon64/Hammer/K8

    [*] Supported processor vendors --->
        [*] Support AMD processors (NEW)

    [*] SMT (Hyperthreading) scheduler support
    [*] Multi-core scheduler support
    [*] Machine Check / overheating reporting
    [*] AMD MCE features

Processor family (MZEN) --->
(X) AMD Zen

Performance monitoring --->
<*> AMD Processor Power Reporting Mechanism

    [*] AMD microcode loading support

    [*] EFI runtime service support
    [*] EFI stub support
    [ ] EFI mixed-mode support

    [*] Built-in kernel command line
    (root=PARTUUID=)

Power management and ACPI options --->
    CPU Frequency scaling --->
        <*> AMD Opteron/Athlon64 PowerNow!
        <*> AMD frequency sensitivity feedback powersave bias

Device Drivers --->
    Generic Driver Options --->
        (amd-ucode/microcode_amd_fam17h.bin) External firmware blobs to build into the kernel binary
        (/lib/firmware) Firware blobs root directory

    Graphics support --->
        <*/M> Direct Rendering Manager (XFree86 4.1.0 and higher DRI support) --->
            [*] Enable legacy fbdev support for your modesetting driver
        <> ATI Radeon
         AMD GPU
            [ /*] Enable amdgpu support for SI parts
                (only needed for Southern Islands GPUs with the amdgpu driver)
            [ /*] Enable amdgpu support for CIK parts 
                (only needed for Sea Islands GPUs with the amdgpu driver)
            [*] Enable AMD powerplay component
            
            ACP (Audio CoProcessor) Configuration --->
            [*] Enable AMD Audio CoProcessor IP support (CONFIG_DRM_AMD_ACP)

            Display Engine Configuration --->
                [*] AMD DC - Enable new display engine
                [ /*] DC support for Polaris and older ASICs
                    (only needed for Polaris, Carrizo, Tonga, Bonaire, Hawaii)
                [ /*] AMD FBC - Enable Frame Buffer Compression
                [ /*] DCN 1.0 Raven family
                    (only needed for Vega RX as part of Raven Ridge APUs)
        <*/M> HSA kernel driver for AMD GPU devices
        
    <*/M> Sound card support --->
        <*/M> Advanced Linux Sound Architecture --->
            [*] PCI sound devices --->
                HD-Audio --->
                    <*> HD Audio PCI
                    [*] Support initialization patch loading for HD-audio
                    <*> whatever audio codec your soundcard needs
                    <*> Build HDMI/DisplayPort HD-audio codec support
                (2048) Pre-allocated buffer size for HD-audio driver

Firmware Drivers --->
    EFI (Extensible Firmware Interface) Support --->
        <*> EFI Variable Support via sysfs

[*] IOMMU Hardware Support --->
    [*] AMD IOMMU support
    <*> AMD IOMMU Version 2 driver

-*- Enable the block layer --->
    Partition Types --->
        [*] Advanced partition selection
        [*] EFI GUID Partition support

Processor type and features 中的 Built-in kernel command line 需填入 /rootinitrd 的路徑,如

root=/dev/nvme0n1p3 rw initrd=/EFI/Gentoo/initramfs-linux.img

Handbook 中關於 RyzenAMDGPUAMD_microcode 的章節為本小節的內容提供了很大的説明。

創建 fstab 文件

倘若依照上文關於 EFISTUB 的配置,fstab 關於 EFI 分區的幾行需要說明綁定掛載的關係。以下是一個例子:

/dev/nvme0n1p1   /esp   vfat    defaults,noatime    0   0
/esp/EFI/Gentoo  /boot  none    defaults,bind       0   0
/dev/nvme0n1p2   none   swap    sw                  0   0
/dev/nvme0n1p3   /      btrfs   ssd,noatime         0   1

使用 blkid 獲取檔案系統各自的 UUID 更換其分區或設備名稱是推薦的做法,要記得加上 UUID= 的首碼。若 SSD 支援 TRIM 命令,可以加入 mount 參數 discard 提升其讀寫性能。如果使用 Btrfs 作為檔案系統,可以加入 mount 參數 ssd,但根據 Btrfs Wiki 中關於 optimization for SSD 的描述,加入了 ssd 參數則無法支持 TRIM/discard,官方也推薦使用 ssd 以獲得更好的相容性。

添加 UEFI 啟動入口

關於 UEFI 啟動入口,Gentoo Handbook 和其它發行版本 Wiki 的推薦是使用 efibootmgr 管理。efibootmgr 著實簡潔方便,卻不能識別 nvme 設備分區資訊,如 /dev/nvme0n1p1 即為非法 disk 參數。鑒於 efibootmgr 只對 sda 情有獨鍾,於是根據 UEFI Shell 相關章節,我使用 Shell 手動添加了入口。

安裝無線網路相關包

再按照 Handbook 配置完網路,不要忘記安裝無線網路的相關包,屆時四處尋找網線而後蹲在路由器邊上的樣子可一點也不優雅 😎

emerge --ask net-wireless/iw net-wireless/wpa_supplicant

結語

話說回來,如果不是 Ryzen 給了我充足的理由,也許我不會上 Gentoo 的船。不論怎樣,感謝它給我的這次豐富的折騰體驗。接下來的幾個月裡,請多多關照 💗