用crash tool觀察ARM64 Linux地址轉換

来源:https://www.cnblogs.com/bigfish0506/archive/2022/05/15/16273091.html
-Advertisement-
Play Games

crash tool是一款內核調試工具,常用來分析內核崩潰問題。我們可以手動觸發內核崩潰,然後借用該工具來分析當時系統的運行情況,當然也包括記憶體的運行情況。 ...


初學者學習Linux系統地址轉換時,如果只是學習理論,又或者研讀代碼,那可能感覺比較枯燥。此時如果可以利用某些工具實際觀察一下地址轉換的過程,那可能會給枯燥的內核學習帶來些微的樂趣。crash tool是一款內核調試工具,常用來分析內核崩潰問題。我們可以手動觸發內核崩潰,然後借用該工具來分析當時系統的運行情況,當然也包括記憶體的運行情況。

本文基於ARMv8 AArch64 (簡稱ARM64)架構,Linux 4.14內核來講述。首先回顧一下記憶體訪問的相關知識點。

1、ARM記憶體訪問的硬體架構

ARM有MMU部件,現代操作系統一般都會啟用MMU來訪問記憶體。啟用MMU之後,多進程就有了可能,每個進程可以維護各自私有的虛擬地址空間,無需關心物理記憶體佈局。

 

2、虛擬地址空間到物理地址空間的映射

虛擬地址到物理地址的映射是通過查表的機制來實現,下圖是一種典型的地址映射佈局。內核空間地址的高16位(bit[63:48])為全1,其轉換表的基地址存放在TTBR1_EL1寄存器中;用戶空間地址的高16位(bit[63:48])為全0,其轉換表的基地址存放在TTBR0_EL0寄存器中。

 

除了高16位外,剩下的48位,也並不全用作虛擬地址空間,使用多少位是可以配置的,比如Linux系統的內核一般做如下配置,表示有39位虛擬地址空間。

CONFIG_ARM64_VA_BITS=39

39位虛擬地址空間,內核空間範圍為0xFFFFFF80_00000000 ~ 0xFFFFFFFF_FFFFFFFF,用戶空間範圍為0x00000000_00000000 ~ 0x0000007F_FFFFFFFF。

 

3、轉換表的格式

轉換表有4個級別,level 0 ~ level 3。

如下圖所示,當bit[1:0]為2b'11時,表示該表項是Table descriptor,指向下一級轉換表的地址。而當 bit[1:0]為2b'01時,表示Block entry,不指向下一級轉換表,而是直接輸出block address。當表項處於level 3時,即使bit[1:0]為2b'11,也不再指向下一級轉換表,而是輸出block address。

 

4、地址轉換的過程

如下圖所示,以39位虛擬地址為例,來瞭解地址轉換過程。圖片是取自ARMv8官方文檔,建議放大了看。

記憶體中維護著三個轉換表,從虛擬地址轉換成物理地址,要經過三次查表的過程。

39位虛擬地址被分成了4部分,作用如下:

  • bit[38:30] —— 索引第一級表中的表項

  • bit[29:21] —— 索引第二級表中的表項

  • bit[20:12] —— 索引第三級表中的表項

  • bit[11:0] —— 頁內偏移

第一步,TTBR寄存器中存放了第一級轉換表的起始地址,虛擬地址的bit[38:30]的值表示要查找轉換表中的第幾項,這個值左移三位(64位地址,每個表項占用8位元組),再加上第一級轉換表的地址,就是該表項的地址。該表項存放的是第二級轉換表的起始地址。

第二步,用第二級轉換表的起始地址,再結合虛擬地址的bit[29:21],與第一步計算方法類似,可以計算出第二級表項的地址。第二級表項中存放了第三級轉換表的起始地址。

第三步,用第三級轉換表的起始地址,再結合虛擬地址的bit[20:12],與第一步計算方法類似,可以計算出第三級表項的地址。第三級表項存放的是最終的頁面描述符,有頁面的物理地址信息,用這個地址再加上虛擬地址的bit[11:0],就是該虛擬地址對應的物理地址。

 

 

5、Linux內核中的關鍵數據結構

mm_struct結構體是記憶體描述符,內核用它來維護一個進程的地址空間的所有信息。這個結構體中包含了一個重要成員:pgd指針,pgd的名稱是頁全局目錄,指向的是第一級轉換表的的起始地址。

 

每個進程的task_struct結構體中,都包含了記憶體描述符。

 

init_mm全局變數,是內核本身的記憶體描述符。

 

有了以上知識點做支撐後,就可以用crash tool來驗證自己的理解了。

 

6、用crash tool觀察地址轉換

手動觸發內核崩潰的shell指令是:

echo "c" > /proc/sysrq-trigger

crash tool使用示例如下:

crash_arm64 vmlinux dumpfile -m phys_offset=0x80000000

進入crash tool環境後,我們選擇1號進程,也就是init進程來分析。首先用bt命令看一下1號進程當前的調用棧。

 

我們選擇該進程TASK的地址和SP寄存器指向的地址來進行實際分析。TASK的高位地址全為1,為內核空間的虛擬地址;SP地址高位全為0,為用戶空間的地址。

先分析用戶空間的虛擬地址 0000007feeac5cb0,將它分解如下:

bit[38:30]    0x1ff ,左移三位是 0xff8

bit[29:21]    0x175,左移三位是 0xba8

bit[20:12]    0x0c5,左移三位是 0x628

bit[11:0]      0xcb0

怎麼找到它對應的物理地址呢?首先要找到第一級轉換表所在的位置,也就是pgd的位置。我們在前面提到過,進程的記憶體描述中有pgd指針。所以我們可以先通過crash tool的task命令查看記憶體描述符的地址,再通過struct命令查看記憶體描述符中pgd指針的值。

 

知道了第一級轉換表所在的位置,結合虛擬地址的bit[38:30],就可以算出虛擬地址在第一級轉換表中所對應的表項位置:0xffffffc01bf60000 + 0xff8 = 0xffffffc01bf60ff8。用rd命令可以讀取這個表項的值,這個值裡面含有第二級轉換表的起始地址信息。

 

讀出的值是99c00003,bit[1:0]=2b'11,表示該表項類型為Table descriptor,指向下一級(第二級)轉換表,起始地址是99c00000。結合虛擬地址的bit[29:21],可以算出虛擬地址在第二級轉換表中的表項地址:0x99c00000 + 0xba8 = 0x99c00ba8。該地址是物理地址,需要用rd -p命令讀取其值,這個值裡面含有第三級轉換表的起始地址信息。

讀出的值是99c04003,表項類型也為Table descriptor。結合虛擬地址的bit[20:12],可以算出虛擬地址在第三級轉換表中對應的表項地址:0x99c04000 + 0x628 = 0x99c04628。三級表項存放的是頁面描述符信息,不再指向下一級轉換表。

從0x99c04628地址讀出的值是00e800008594bf53,結合第4節的地址轉換過程圖,bit[47:12]存放的是地址信息,與虛擬地址的bit[11:0](頁內偏移)結合後,就構成了實際的物理地址:0x8594b000 + 0xcb0 = 0x8594bcb0。這個地址就是0x0000007feeac5cb0所對應的物理地址。

上述過程我們手動計算出了物理地址,那如何知道有沒有算對呢?其實crash tool提供了vtop這個命令,可以直接顯示虛擬地址到物理地址的轉換結果,如下圖所示。可以看到vtop命令的結果和我們手動計算的結果一致,說明我們對轉換過程的理解是正確的。

 

再來分析內核空間的虛擬地址 ffffffc01bf60000,將它分解如下:

bit[38:30]    0x100,左移三位是 0x800

bit[29:21]    0x0df,左移三位是 0x6f8

bit[20:12]    0x160,左移三位是 0xb00

bit[11:0]     0x000

首先我們要知道內核空間的 pgd,結合前面第4節講的Linux關鍵數據結構,內核空間的 pgd 是保存在 init_mm 變數中,用p命令列印變數結果,可以看到pgd指針的值。

 

每一級表項的計算過程與用戶空間例子類似,可以得到如下觀察結果:

 

註意,第二級表項的值是00f800008be00f11,bit[1:0]=2b'01,表示Block entry,不再指向下一級轉換表,而是指示物理地址,地址值為9be00000。

兩級轉換表對應的是虛擬地址的bit[38:30]和bit[29:21],又沒有第三級轉換表,因此剩下的bit[20:0]都是頁內偏移。所以計算出最終物理地址為:0x9be00000 + 0x160000 = 0x9bf60000。也就是說, ffffffc01bf60000的物理地址是9bf60000。

用vtop命令驗證,和手動計算的結果一致。

 

------ END ------

作者:bigfish99

博客:https://www.cnblogs.com/bigfish0506/

公眾號:大魚嵌入式


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • pip是個安裝包的軟體,conda是個環境管理的工具。conda能夠安裝多個python解釋器,pip不行。conda install這種方式安裝的庫都會放在/Users/orion-orion/miniforge3/pkgs目錄下。這樣的好處是,當在某個環境下已經下載好了某個庫,再在另一個環境中還... ...
  • 閱讀目錄 效果展示 準備 簡單說明 + 源碼 結尾(視頻及源碼倉庫) 1. 效果展示 欣賞效果: 2. 準備 創建一個WPF工程,比如站長使用 .NET 7 創建名為 WalletPayment 的WPF項目。 這次我們不添加任何圖片,只添加了一個Nuget包 MaterialDesignTheme ...
  • 這篇文章只是我學習Web API框架的輸出,學習方法還是輸出倒逼輸入比較行得通,所以不管寫的好不好,堅持下去,肯定有收穫。篇幅比較長,仔細思考閱讀下來大約需要幾分鐘。 做.NET開發有好幾年時間了,從很久之前的WebForm到MVC,再到目前前後端分離模式下RESTful風格的 Web API ,相 ...
  • 遷移的初衷 本人平時是做.net相關的工作,對於.net技術棧也有一些瞭解,自從新的.net能夠跨平臺之後,之前也有跨平臺的ui框架Xamarin,現在微軟推出了.NET MAUI這個說是 統一了開發體驗,而且都RC版本了,所以本人也就想著試試看了,於是就想著把前幾天的WinUI的demo遷移到MA ...
  • 基於dhtmlxGantt實現的甘特圖組件,目前僅做到了數據展現,方法及插槽暫未實現,若需可按照dhtmlxGantt的文檔及微軟的Balzor文檔,自行擴展。 數據發生變化後甘特圖會立即發生變化。 目前上不支持甘特圖的事件回調及顯示內容的擴展,若需要請按照dhtmlxGantt的文檔及微軟的Bal ...
  • 在實際項目開發中,我們可能會碰到各種各樣的項目環境,有些項目需要一個大而全的整體框架來支撐開發,有些中小項目這需要一些簡單便捷的系統框架靈活開發。本系列隨筆介紹底層利用SqlSugar來做ORM數據訪問模塊,設計一個簡單便捷一點的框架,本篇從基礎開始介紹一些框架內容。 ...
  • 配置三台伺服器,如下: 生成密鑰 在三台機器(node1\node2\node3)執行以下命令,生成公鑰與私鑰。 ssh-keygen -t rsa 執行該命令之後,按下三個回車即可,然後敲(三個回車),就會生成兩個文件id_rsa(私鑰)、id_rsa.pub(公鑰),預設保存在/root/.ss ...
  • df命令 linux命令學習_ll linux命令學習_pip linux命令學習_cat df命令:顯示磁碟的相關信息 語法:df [-ahHiklmPT][--block-size=<區塊大小>][-t <文件系統類型>][-x <文件系統類型>][--help][--no-sync][--sy ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...