Linux 在 M1 上跑起來(lái)了

轉(zhuǎn)自:CSDN
蘋(píng)果 M1 芯片引發(fā)行業(yè)大熱,芯片的發(fā)展也將影響著未來(lái)行業(yè)的走向。今天,隨著本文一起來(lái)看看如何把 Linux 移植到 M1。
自 2014 年 iPhone 6 發(fā)布以來(lái),蘋(píng)果就在集中精力構(gòu)建更快的芯片,相對(duì)于在一塊芯片上加載更多核心,他們更加注重單線(xiàn)程性能的提高。他們內(nèi)部的硬件設(shè)計(jì)團(tuán)隊(duì)采用了這種方法,并生產(chǎn)出了功能多樣且獨(dú)一無(wú)二的芯片,從而奠定了他們?cè)诩軜?gòu)特征方面的行業(yè)領(lǐng)先地位。
2020 年 11 月,蘋(píng)果發(fā)布的新品臺(tái)式機(jī)搭載了 M1 處理器,不少人都為該系統(tǒng)的出色性能而贊不絕口。
事實(shí)上,Linux 之父 Linus Torvalds 也曾在國(guó)外 Real World Technologies 網(wǎng)站的留言板答網(wǎng)友提出的“如何看待新的(M1 芯片)蘋(píng)果電腦”問(wèn)題時(shí),回應(yīng)稱(chēng):
如果它運(yùn)行 Linux ,我絕對(duì)希望擁有一臺(tái)。
此前,CSDN 也曾報(bào)道過(guò)安全顧問(wèn) Hector Martin 正在眾籌平臺(tái) Patreon 上啟動(dòng)了一項(xiàng)向 M1 Mac 移植 Linux 的項(xiàng)目(https://www.patreon.com/marcan),并且得到不少開(kāi)發(fā)者的響應(yīng)。而本文作者也一直在努力為安全研究人員提供有關(guān)操作系統(tǒng)和程序如何在蘋(píng)果 ARM 處理器上運(yùn)行的深刻見(jiàn)解。因此,當(dāng)蘋(píng)果決定允許在帶有M1處理器的 Mac 上安裝自定義內(nèi)核時(shí),他們決定嘗試一番。
開(kāi)始將 Linux 移植 M1
M1 的許多組件都是與蘋(píng)果的移動(dòng) SoC 共享的,因此可以從這個(gè)地方入手。但是,在編寫(xiě) Linux 驅(qū)動(dòng)程序時(shí)發(fā)現(xiàn),實(shí)際上蘋(píng)果的 SoC 非常不標(biāo)準(zhǔn)。由于筆者的虛擬環(huán)境非常靈活,能夠適應(yīng)多種模型,但在 Linux 上,64 位 ARM 主要依賴(lài)于一系列定義良好的組件和固件接口,但 M1 幾乎沒(méi)有使用任何這類(lèi)的組件或固件接口。
首先,蘋(píng)果的 CPU 采用了不同的方式來(lái)引導(dǎo)操作系統(tǒng)內(nèi)核。引導(dǎo)加載程序(稱(chēng)為 iBoot)加載一個(gè) Mach-O 格式的可執(zhí)行目標(biāo)文件,該文件支持壓縮,并封裝在一種經(jīng)過(guò) ASN.1 簽名的 IMG4 格式中。與之相比,正常的 64 位 ARM 上的 Linux 則由一個(gè)普通的二進(jìn)制鏡像引導(dǎo)(支持壓縮,也支持幾種容器格式),或者在 UEFI 平臺(tái)上由 Windows 風(fēng)格的“PE”可執(zhí)行文件引導(dǎo)。
CPU 核心啟動(dòng)之后,真正的問(wèn)題來(lái)了。在其他 64 位 ARM 系統(tǒng)上,這一步通常是通過(guò) PSCI 接口調(diào)用固件(一些系統(tǒng)采用了輪詢(xún)表,但依然需要固件)。但在 M1 上,CPU 核心從一個(gè) MMIO 寄存器指定的地址處開(kāi)始(MMIO 寄存器由內(nèi)核鏡像設(shè)置成某個(gè)特定的偏移量,然后由引導(dǎo)程序鎖定),然后直接開(kāi)始運(yùn)行內(nèi)核。
除此之外,蘋(píng)果還設(shè)計(jì)了自己的中斷控制器 Apple Interrupt controller(簡(jiǎn)稱(chēng) AIC),這個(gè)控制器與任何主流 ARM GIC 標(biāo)準(zhǔn)都不兼容。不僅如此,其定時(shí)器中斷并沒(méi)有像通常的 ARM 那樣連接到每個(gè) CPU 中斷上,而是路由到 FIQ 上。FIQ 是一個(gè)很難理解的架構(gòu)特性,在老式的 32 位 ARM 處理器上經(jīng)常使用。很顯然,Linux 內(nèi)核并不支持通過(guò) FIQ 發(fā)送中斷,所以我們必須自己實(shí)現(xiàn)。
系統(tǒng)內(nèi)的多個(gè)處理器互相通信需要一組處理器間中斷(IPI)。在舊的蘋(píng)果 SoC 上,這些中斷的處理方式與 IRQ 相似,即執(zhí)行 MMIO 并訪(fǎng)問(wèn) AIC。但在新的處理器上,蘋(píng)果使用了一組處理器核心寄存器來(lái)分發(fā)并通知 IPI,而且也路由到了 FIQ 上。所以 FIQ 的支持非常重要。
在處理了一些其他的硬件特性之后,筆者團(tuán)隊(duì)添加了一個(gè)預(yù)加載器,作為啟動(dòng)處理器核心的跳板,這樣就可以設(shè)置幀緩沖區(qū),并看到 Linux 啟動(dòng)時(shí)的企鵝了。
需要更多輸入
不幸地是,筆者團(tuán)隊(duì)并沒(méi)能用上 M1 Mac 上的 UART 線(xiàn),所以只能通過(guò)其他方式來(lái)添加鍵盤(pán)(甚至鼠標(biāo))。M1 Mac Mini 有三種方式來(lái)實(shí)現(xiàn)這一點(diǎn):M1 芯片上內(nèi)置的 USB 宿主(提供 Thunderbolt/USB 接口),PCIe 上的 xHCI USB 宿主(提供 A 類(lèi)接口),以及藍(lán)牙。
團(tuán)隊(duì)并沒(méi)有打算深入研究蘋(píng)果的藍(lán)牙,但大家注意到它使用了一種非標(biāo)準(zhǔn)的 PCIe 協(xié)議,而且不僅需要使用 M1 芯片上的 PCIe 接口,還需要為該協(xié)議編寫(xiě)自定義的內(nèi)核驅(qū)動(dòng)程序。這不是個(gè)理想的選擇。
也就是說(shuō),只能選擇 PCEe 并使用標(biāo)準(zhǔn)的內(nèi)核 xHCI 驅(qū)動(dòng),或者使用內(nèi)置的 USB 控制器。蘋(píng)果很早以前就在其芯片里使用了 Synopsys DWC3 雙角色 USB 控制器,而且該控制器有 Linux 內(nèi)核驅(qū)動(dòng)。不幸的是,蘋(píng)果又給該控制器添加了自定義的邏輯,所以這里也需要大量工作。
M1 的 PCIe 和內(nèi)置的 DWC3 USB 控制器都使用 IOMMU,稱(chēng)為 DART。蘋(píng)果一直在改進(jìn)其 DART 設(shè)計(jì),因此 IOMMU 的功能很齊全。最新版甚至支持子頁(yè)面內(nèi)存保護(hù),這是在其他控制器中從未有過(guò)的。
為了將 M1 中的 USB 端口連接到 Mac Mini 背后的 USB C 口連接器上,團(tuán)隊(duì)需要使用 I2C 上的芯片(意味著需要提供 GPIO 和 I2C 驅(qū)動(dòng)程序),這兩者都使用了自定義固件。
在研究了幾天 USB 后,大家終于能夠連接到外部的 USB 集線(xiàn)器上并成功地連上了鍵盤(pán)、鼠標(biāo)和閃存盤(pán),從此就可以運(yùn)行正常的 Linux 桌面版了。
操作指南
下載 Ubuntu rootfs
在 Mac Mini M1 上引導(dǎo) Linux 的第一步就是下載 Ubuntu POC 的 rootfs。我們采用了樹(shù)莓派的鏡像,因?yàn)樗?live 版本的 USB 啟動(dòng)鏡像,所以只需要做出細(xì)微的修改即可。
解壓縮鏡像
你需要至少 16 G 的外置 USB。執(zhí)行下列命令解壓縮鏡像:
tar?-xjvfubuntu-20.10-preinstalled-desktop-arm64+raspi.img.bz2
然后,使用磁盤(pán)工具找到外部 USB 的名稱(chēng)。最后,執(zhí)行下列命令將鏡像復(fù)制到 USB 上:
sudo?dd?if=ubuntu-20.10-preinstalled-desktop-arm64+raspi.img?of=/dev/rYOURUSBDISK?bs=1m
連接到 Mac
通過(guò) USB C 口適配器,將 USB 插入 Mac Mini M1 上。目前不支持 A 口。
引導(dǎo)至
為了引導(dǎo)至 1TR(真正的恢復(fù)操作系統(tǒng)),請(qǐng)關(guān)閉 Mac Mini M1,然后按住電源鍵,直到看到“l(fā)oading options”。加載完成之后,從頂端的菜單中選擇終端選項(xiàng)。
安裝自定義內(nèi)核
下一步就是安裝自定義內(nèi)核。筆者團(tuán)隊(duì)編寫(xiě)了一個(gè)腳本來(lái)減輕你的負(fù)擔(dān)。只需要運(yùn)行:
/bin/bash?-c?"\$\(curl?-fsSL?https://downloads.corellium.info/linuxsetup.sh\)"
該腳本會(huì)詢(xún)問(wèn)用戶(hù)名和密碼??吹健癒ernel installed”提示后就可以重啟了。
登錄
系統(tǒng)引導(dǎo)之后就會(huì)提示你登錄。用戶(hù)名為“pi”,密碼為“raspberry”。root密碼也是“raspberry”。
恢復(fù) MacOS
如果想恢復(fù)至 MacOS,只需在 1TR 中打開(kāi)終端,執(zhí)行 bputil -n 即可。
參考鏈接:https://corellium.com/blog/linux-m1
