torvalds

Stars and mentions

Last 30 days, Oct 4 – Nov 2

GitHub stars3,111
mentions79
04284126168Oct 4Oct 18Nov 2
UTC days · repositories torvalds owns10 repositories

Package downloads

Cumulative recorded downloads · since 2025-10-25

npm284
071142213284Oct 4Oct 18Nov 2
Oct 23npm: 1/1 packages observed

Across 1 known packages in repositories torvalds owns. Cumulative totals include recorded downloads before the selected range. Missing observations leave gaps; totals may be incomplete.

Top repositories

torvalds’s repositories ranked by new stars, as on trending.

Loading

Contributes to

Repositories outside torvalds’s account where torvalds opened or reviewed pull requests in the past 365 days.

Who noticed torvalds

Everyone who starred or forked torvalds’s repositories since the archive began in 2011.

Notable accounts

Ordered by the stars their own repositories have received.

Biggest fans

Accounts that starred the most of these repositories.

Breakout weeks

Each repository’s best week of new stars, with the release published around it.

Mentions

80posts
Nov 33 posts
  1. Ubuntuの仮想化基盤(KVM)にRadeon GPU パススルーを設定するには 1. はじめに 1.1 前書き  昨今、エンタープライズ向けLLMの性能が飛躍的に上昇しており非常に使い勝手が良くなってきています。また、ローカル LLM も性能が上がってきており、仕事で使う機会がたまにあります。  用途にも依存しますが、ローカル LLM でも十分な性能を発揮する時があります。そういった点で自宅の倉庫で眠っていたRX 6800 XTがあることを思い出し、ローカル LLM を構築してみようかなと思いました。  自宅で仮想化基盤(KVM)を使っているため、この基盤の仮想マシンで GPU を使えるようにする方法を整理し、その手順を、自分の整理も兼ねて記事にまとめました。  最終的な目的は、仮想マシンでローカル LLM を動かすことです。この記事では、その土台として、仮想マシンで GPU が認識されるところまでを扱います。ゲストOSでの ROCm の導入や、ローカル LLM の実行は扱いません。  そのため、ホストマシンで直接AIを動かす場合やDockerコンテナでの利用では、この記事の設定は参考になりません。  趣味で構築した内容で、調査にはAIも使っています。間違いや、より良い方法があれば、教えていただけると幸いです。 1.2 今回使用するハードウェア・ソフトウェア構成 1.2.1 ハードウェア構成 CPU: AMD Ryzen 7 2700X マザーボード: X470 AORUS ULTRA GAMING メモリ: 32GB GPU1(パススルー用・PCIe 1 Slot): AMD Radeon RX 6800 XT GPU2(ホストOS用・PCIe 3 Slot): NVIDIA GeForce GT 710 1.2.2 ソフトウェア構成 ホストOS OS: Ubuntu Server 26.04 LTS カーネル: 7.0.0-42-generic QEMU: 10.2.1 libvirt: 12.0.0 ゲストOS OS: Ubuntu Server 26.04 LTS 2. 仮想化基盤(KVM)でGPUを使うには  この記事では、次の用語を使い分けます。「ホスト」だけでは、ハードウェアを指すのか OS を指すのかが分からないためです。 用語 意味 ホストマシン 物理的なコンピュータ(ハードウェア全体) ホストOS ホストマシン上で直接動く OS。KVM を動かす側(この記事では Ubuntu Server) 仮想マシン ホストOSが作る、仮想のコンピュータ ゲストOS 仮想マシンの中で動く OS  この章では仮想化基盤(KVM)でGPUを活用するにはどのような方法があるかを整理します。 2.1 仮想マシンで GPU を使う方法  仮想マシンの中で動くゲストOSは、ホストOSのドライバをそのまま使えません。そのため、仮想マシンで GPU を使う方法は、以下の表で3つの項目に整理されます。 方式 GPU 制御OS 割り当て方式(共有・分割・単一) ゲストOSから見える GPU 仕組み 準仮想化(virtio-gpu:VirGL、Venus など) ホストOS 共有 汎用の仮想 GPU ゲストOSの描画・計算の命令をホストOSに転送し、ホストOSのドライバが GPU で実行する ハードウェア分割(NVIDIA vGPU、SR-IOV など) ゲストOS 分割 分けられた仮想 GPU 1枚の GPU を複数の仮想 GPU に分け、それぞれをゲストOSに渡して直接操作させる パススルー ゲストOS 単一 実物の GPU GPU を丸ごと1台の仮想マシンに渡し、ゲストOSに直接操作させる 3. ローカル LLM の実行を見据えた、GPU の割り当て方式の選択  最終的には、仮想マシンでローカル LLM を動かします。そのため、LLM が GPU で計算するために使うソフトウェア(ROCm / CUDA など。3.1節で説明します)が動く方式を、2章の3つから選びます。 3.1 ローカル LLM で使う GPU のソフトウェア  ローカル LLM が GPU で計算するには、計算用のライブラリやソフトウェアが必要です。GPU は CPU とは異なり、独自の処理系を持つためです。このソフトウェアは、AMD の Radeon なら ROCm、NVIDIA の GeForce なら CUDA です。ただし、これらを使えるかどうかは、GPU・OS・ソフトウェアのバージョンの対応状況によります。たとえば、ROCm 10.1.0 の対応表に、この記事で使う RX 6800 XT は載っていません(載っていないことは、動作しないことの証明ではありません)。古い GPU やAMD、NVIDIA以外の GPU を使う場合は、Vulkan などもあります。  そのため、どの方式でも、これらのソフトウェアが使えることが前提になります。Vulkan に対応するランタイムは、ベンダー純正のソフトウェアに比べて限られます。したがって、Vulkan は、純正のソフトウェアが対応していない古い GPU などで使う位置づけと考えています。 3.2 ローカル LLM にはどの方式が現実的か  この節では、2.1節 の3つの方式のそれぞれで、3.1節 のソフトウェア(ROCm / CUDA、Vulkan)が使えるかを整理し、ローカル LLM に現実的な方式を選びます。 方式 ROCm / CUDA Vulkan 使うための GPU・ライセンスの条件 準仮想化(virtio-gpu) 使えない 使える(Venus) ホストOSの対応ドライバと Vulkan の拡張機能、ゲスト・ホスト側のソフトウェア(virglrenderer、Mesa、カーネルなど)の条件が必要で、条件を満たしてもすべてのドライバで動くとは限らない ハードウェア分割(vGPU など) 対応する GPU のみ 対応する GPU のみ 対応する GPU が限られ、公式の資料では一般向けの GPU は対象として確認できない。NVIDIA vGPU は、対応 GPU がデータセンター向けなどで、対応 GPU の一覧に GeForce は含まれず、ライセンスが必要で、CUDA を使えるかは vGPU の種類・GPU・ソフトウェアのバージョン・ライセンスによる。AMD の MxGPU は、公式の対象が Instinct と Radeon PRO V710 で、Radeon RX は一覧にない パススルー 対応する GPU・OS であれば使える 使える 一般向けの GPU でも使える  ROCm / CUDA は、純正のカーネルドライバ(amdgpu、nvidia)が実物の GPU を直接操作することを前提に動きます。準仮想化では、ゲストOSから実物の GPU が見えない(2.1節の表)ため、使えません。ハードウェア分割は、対応する GPU とライセンスの条件が厳しく、公式の資料では一般向けの GPU が対象として確認できません。したがって、一般向けの GPU で純正ソフトウェア(ROCm / CUDA)を使うなら、現実的な方法はパススルーです。 3.3 コンテナ(Docker)はなぜ GPU を簡単に使えるのか  ここでコンテナで GPU を使用する際に、上記の仮想マシンと違い、なぜ簡単に使えるのかを整理します。  結論から言うと、コンテナはホストOSのカーネルを使用するため、ホストOSのGPUドライバをそのまま利用できるからです。 GPU は、カーネルのドライバ(Radeon なら amdgpu)が操作するデバイスです。 コンテナはホストOSのカーネルをそのまま使います。ホストOSのドライバが GPU を管理し、コンテナにはデバイスノード(/dev/dri/*、/dev/kfd など)とライブラリを見せるだけです。そのため、ホストOSのGPUドライバをそのまま使え、複数のコンテナで GPU を共有することもできます。 仮想マシンの中で動くゲストOSは自分のカーネルを持ちます。ゲストOSのカーネルは、ホストOSのドライバを使えません。  この違いが、2.1節 の表で GPU を操作する OS が、ホストOS(準仮想化)とゲストOS(ハードウェア分割、パススルー)に分かれる理由です。 4. GPU パススルーの設定概要  3章の結果、ローカル LLM を動かす仮想マシンには、GPU パススルーが現実的だと分かりました。そのため、この記事ではGPU パススルーを採用します。  この章では、仮想化基盤(KVM)で GPU パススルーを設定するための全体像を示します。IOMMU の仕組みは5章で、それぞれの設定手順は6章以降で説明します。 4.1 全体像  GPU パススルーを実現するためには、以下のような手順が必要です。 BIOSでIOMMU(デバイスのメモリアクセスを制御する機能)を有効化し、起動時に表示するGPUを指定する OSでIOMMUが有効になっていることを確認する VFIO(デバイスを仮想マシンに直接渡すためのLinuxカーネルの仕組み)のモジュールをロードし、GPUをVFIOにバインド(GPUを担当するドライバをVFIOにすること)する 仮想マシンにGPUを割り当てる  これらの手順を順に設定していくことで、仮想マシンでGPUを直接利用できるようになります。 5. IOMMU について  4章の GPU パススルーを実現するための、全体像を提示しました。その全体像で、IOMMUという新たな用語が出てきたと思います。IOMMUはパススルーをする上では必須ですが、どういった仕組みなのかを理解しておいた方が良いと考えています。そのため、この章では、IOMMU が必要になる理由と、IOMMU の仕組みを整理します。設定手順は6章以降で説明します。 5.1 GPU とメモリのやり取り(DMA)  IOMMU の役割を理解するために、先にホストマシンで GPU を使って計算をする際に、データがどのようにやり取りされるかを整理します。  GPU が計算に使うデータは、まずメインメモリ(RAM)に置かれます。CPU 上のドライバは、GPU に「どのアドレスのデータを使うか」を伝えます。GPU は、そのアドレスのメモリを、CPU を介さずに直接読み書きします。この仕組みを DMA(Direct Memory Access)と言います。計算結果も同様に、GPU がメモリに書き込み、CPU がそれを読み取ります。  ここで重要なのは、次の2点です。 アドレスを決めるのは、GPU ではなくドライバです。 GPU は、伝えられたアドレスをそのまま使って読み書きします。 5.2 仮想マシンのメモリの扱い  次に、仮想化基盤での仮想マシンのメモリの扱いを整理する必要があります。ここでは、仮想マシンのメモリが、ホストマシンのメモリとどう対応づけられているかを整理します。  なお、以降に出てくるメモリの番地は、仕組みを説明するために簡略化した値です。実際のアドレスは 16 進数で表記され、もっと大きな値になります。  ゲストOSや、その起動用のファームウェアは、使うアドレスが決まっています(たとえば、BIOS で起動する x86 では、0 番地付近を割り込みベクタテーブルなどが使います)。そのため、ホストマシンのメモリの 100〜200 番地を仮想マシンに割り当てる場合でも、ゲストOSには 100〜200 番地ではなく、0〜100 番地のメモリがあるように見せます。ホストOSは「ゲストOSの 0〜100 番地 = ホストマシンの 100〜200 番地」という変換表を持ちます。仮想マシンの CPU がメモリにアクセスするときは、CPU がこの表で変換します(AMD では NPT、Intel では EPT と呼ばれる仕組みです)。  上記の説明でもある通りこのメモリのアドレス変換は CPU が担います。そのため、CPU を介さずにメモリ書き込みをする DMA では、この変換表が使われません。 ゲストOS側のドライバが提示するアドレスはあくまでゲスト物理アドレスです。 GPUはこの指定されたアドレスにアクセスしますが、変換表を通らないため、ホストマシンの実メモリを書き換えてしまいます。  例を提示するとゲストOSで 50 番地を指定した場合、GPUはホストマシンの 50 番地にアクセスしてしまうということです。 アドレスの食い違いにより、ホストOSや他の仮想マシンが使っているメモリを、ゲストOS側に悪意がなくても書き換えるおそれがあります。 ゲストOS側が悪意のあるユーザに操作されることがある場合に、任意のアドレスを GPU に指定されると、ホストマシン全体のメモリを読み書きされるおそれがあります。 5.3 IOMMUとは  5.2節 の問題を解決するのが、IOMMU(Input-Output Memory Management Unit)です。IOMMU は、GPU が DMA で使うアドレスを、ホストOSがあらかじめ設定した変換表で変換し、割り当てたメモリの範囲だけにアクセスを制限するハードウェア機能です。5.2節 の例では、ゲストOSのドライバが指定した 50 番地への DMA は、ホストマシンの 150 番地に届きます。割り当てた範囲(ゲストOSの 0〜100 番地)の外へのアクセスは遮断されます。  ホストOSは、デバイスから見えるアドレスがゲスト物理アドレスになるように、IOMMU の変換表を作ります。5.2節 で CPU が使っている表と同じ対応(ゲスト物理アドレスからホストマシンのアドレス)を、IOMMU にも登録します。そのため、ゲストOSのドライバは、IOMMU の有無を意識せず、自分のメモリのアドレスをそのまま GPU に渡せます。データのやり取りは、次のようになります(5.2節 と同じ数値の例です)。 ゲストOS上のプログラムが、ゲストOSの 50 番地にデータを書きます。CPU が変換し、ホストマシンの 150 番地に書かれます。 ゲストOSのドライバが、GPU に「50 番地を読め」と指示します。 GPU が 50 番地を DMA で読みます。IOMMU が変換し、ホストマシンの 150 番地から、手順 1 のデータを読みます。 結果は、逆向きに同じ経路をたどります。GPU が 80 番地に書くと、IOMMU がホストマシンの 180 番地に書き込みます。ゲストOSが 80 番地を読むと、CPU が同じ 180 番地を読みます。  上記の説明でIOMMUが必要な理由が見えてくると思います。そのため、Linux カーネルの VFIO(Virtual Function I/O) では、メモリを安全に管理するため、IOMMU がない環境でデバイスを仮想マシンに割り当てることに対応していません。GPU パススルーには、IOMMU を有効にする必要があります。なお、VFIO には IOMMU がない環境でデバイスを使うための No-IOMMU モードがありますが、安全性が確保されず、仮想マシンへのデバイス割り当てには使えません。  IOMMU が分離できる単位は、デバイス1つとは限りません。複数の機能を持つデバイスでは、機能同士のやり取りが IOMMU を通らない場合があるためです。そのため、他から分離できるデバイスの集まりを IOMMU グループと呼び、VFIO もグループ単位でデバイスを扱います。たとえば GPU の映像機能と音声機能は、同じグループに入ることがあります。 6. BIOS 設定  6章からは、実際にGPU パススルーをするための手順を書いていきます。  BIOSの設定では、IOMMUの有効化と仮想化設定(SVM Mode)の設定、今回の環境での映像出力優先設定をします。 6.1 IOMMU の有効化  BIOSの設定はメーカごとで異なります。今回は私のマザーボードの例を示します。実際の設定はお使いのマザーボードのマニュアルを参照してください。  AMD の CPU では、BIOS で次の2つを有効にします。項目名は機種や BIOS のバージョンで異なります。 仮想化(SVM Mode) IOMMU 実際に設定する流れを以下の画像に示します。赤枠が操作する項目です。 6.1.1 仮想化(SVM Mode)の有効化 「M.I.T.」タブの「高度な周波数設定」を開く。 「高度なCPUコア設定」を開く。 「SVM Mode」を「有効」にする。 6.1.2 IOMMU の有効化 「チップセット」タブを開き、「IOMMU」を「有効」にする。  今回の環境はAMDの CPU のため、Intel の CPU の場合や、マザーボードによって設定項目が異なります。それは設定者が確認してください。 6.2 映像出力優先設定 ! CPUに内蔵 GPU があり、ホストの起動時表示に使える構成では、この設定が必要でない場合があります。必要に応じて、映像出力の優先設定を確認してください。 今回の環境では内蔵GPUがないCPUのため、1枚のGPUにするとパススルー後は映像出力用のデバイスがないため、非常に困ります。 そのため、今回は映像出力用のGPUを搭載して、パススルーする GPU とは別のGPUをホストOS用にします。この構成の場合、ホストOS用の GPU をメインの映像出力先にしないと不都合が出ます。  BIOS/UEFI の画面、ブートローダ、OS の起動中の表示を、どの GPU から出すかを選ぶ設定です。Initial Display Output、Primary Display、Primary VGA などの名前で、「PCIe 1 スロット」「内蔵 GPU」のように選びます。  ホストOS用の NVIDIA GPU(PCIe 3 Slot) を選びます。パススルーする GPU が起動時の表示に使われると、ホストOSのフレームバッファや、起動時に書き換えられた GPU の初期化データ(VBIOS)が、仮想マシンでの GPU の初期化を妨げることがあるためです。 設定例を以下に示します。 「周辺機器」タブを開き、「Initial Display Output」を「PCIe 3 Slot」にする。  変更が完了したら、変更を保存して再起動します。 6.3 OSでBIOS設定が反映されているかの確認  BIOSで設定した内容が、OSに反映されているかを確認します。 6.3.1 前提(パススルーする GPU の認識確認)  まず、設定の確認をする前に OS でGPUが認識されていることを確認します。認識されていない場合は、物理的な接続状況や故障していないかを確認する必要があります。 6.3.1.1 映像機能の認識確認  まず、映像機能が認識されていることを確認します。以下のコマンドを実行し、想定される出力例を示します。デバイスが出力されていれば問題ありません。 lspci -nn | grep -i -E "vga|3d|display" 想定される出力例 07:00.0 VGA compatible controller [0300]: NVIDIA Corporation GK208B [GeForce GT 710] [10de:xxxx] (rev a1) 0b:00.0 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Navi 21 [Radeon RX 6800/6800 XT / 6900 XT] [1002:xxxx] (rev c1)  上記のコマンドの出力例の先頭に記載されている 0b:00.0 が PCI アドレス、末尾のほうに記載されている [1002:xxxx] が PCI ID です。この 2 つは、表すものが違います。このIDとアドレスは設定する項目ごとで異なります。そのため、IDとアドレスは控えておいてください。 情報 例 表すもの PCI ID 1002:xxxx デバイスの種類(ベンダーと型番) PCI アドレス 0b:00.0 デバイスの場所(ホストマシンのどこに挿さっているか)  同じ型番の GPU を2枚挿している場合、PCI ID は同じですが、PCI アドレスは違います。 6.3.1.2 音声機能の確認  GPU は、映像のほかに音声(HDMI/DP オーディオ)を扱う機能を持っています。VFIO でホストOSから切り離す単位は、デバイスではなく IOMMU グループ(5.3節)で、映像機能と音声機能は同じグループに入ることが多いです。同じグループに属する場合は、音声機能も一緒に切り離す必要があるため、音声機能の PCI ID も確認します。  なお、音声機能を仮想マシンに渡すかどうかは別の話です。仮想マシンで音声を使わない用途(ローカル LLM の計算だけに使う場合など)であれば、渡さなくて構いません。  同じカードの機能は、PCI アドレスのバス番号とスロット番号(0b:00)を指定すると全て表示されます。そこから音声の行だけを取り出します。0b:00 は 6.3.1.1 の例です。 lspci -nn -s 0b:00 | grep -i audio 想定される出力例 0b:00.1 Audio device [0403]: Advanced Micro Devices, Inc. [AMD/ATI] Navi 21/23 HDMI/DP Audio Controller [1002:yyyy]  6.3.1.1 と 6.3.1.2 で表示された PCI ID(映像機能と音声機能)は、控えておいてください。IOMMUや設定で使う値です。 6.3.2 SVM Mode / IOMMU の有効化確認 6.3.2.1 SVM Mode の有効化確認  まず、SVM Mode が有効になっていることを確認します。 カーネルのバージョンを確認 uname -r 想定される出力例 7.0.0-42-generic SVM が有効か確認 grep -c -w svm /proc/cpuinfo 想定される出力例 1以上であればSVMが有効 16  カーネルのバージョンが 6.7 以上で、2つ目のコマンドが 1 以上を表示すれば、有効です。6.7 未満では、BIOS で無効でも svm が表示されることがあるためです。 6.3.2.2 IOMMU の有効化確認  次に、IOMMU が有効になっていることを確認します。 ! Ubuntu 26.04 では、IOMMU を有効にするカーネルパラメータの設定は不要です。ですが、古いOSや他のディストリビューションでは、intel_iommu=onなどのカーネルでIOMMUを有効にする設定が必要になる場合があります。 今回使用するカーネル(7.0.0-42-generic)は CONFIG_AMD_IOMMU=y、CONFIG_INTEL_IOMMU_DEFAULT_ON=y でビルドされており、BIOS で有効にすれば、カーネルが自動でIOMMUを有効にします。ビルド設定は grep -E 'CONFIG_AMD_IOMMU=|CONFIG_INTEL_IOMMU_DEFAULT_ON' /boot/config-$(uname -r) で確認できます。 sudo dmesg | grep -i -e AMD-Vi -e IOMMU 想定される出力例 [ 0.000000] AMD-Vi: Using global IVHD EFR:0xf77ef22294ada, EFR2:0x0 [ 0.283728] iommu: Default domain type: Translated [ 0.283728] iommu: DMA domain TLB invalidation policy: lazy mode [ 0.329182] pci 0000:00:00.2: AMD-Vi: IOMMU performance counters supported [ 0.329335] pci 0000:00:01.0: Adding to iommu group 0 [ 0.329367] pci 0000:00:01.3: Adding to iommu group 1 [ 0.329409] pci 0000:00:02.0: Adding to iommu group 2 [ 0.329467] pci 0000:00:03.0: Adding to iommu group 3 [ 0.329498] pci 0000:00:03.1: Adding to iommu group 4 [ 0.329540] pci 0000:00:04.0: Adding to iommu group 5 [ 0.329596] pci 0000:00:07.0: Adding to iommu group 6 [ 0.329627] pci 0000:00:07.1: Adding to iommu group 7 [ 0.329682] pci 0000:00:08.0: Adding to iommu group 8 [ 0.329713] pci 0000:00:08.1: Adding to iommu group 9 [ 0.329770] pci 0000:00:14.0: Adding to iommu group 10 [ 0.329800] pci 0000:00:14.3: Adding to iommu group 10 [ 0.329931] pci 0000:00:18.0: Adding to iommu group 11 [ 0.329961] pci 0000:00:18.1: Adding to iommu group 11 [ 0.329991] pci 0000:00:18.2: Adding to iommu group 11 [ 0.330020] pci 0000:00:18.3: Adding to iommu group 11 [ 0.330049] pci 0000:00:18.4: Adding to iommu group 11 [ 0.330078] pci 0000:00:18.5: Adding to iommu group 11 [ 0.330107] pci 0000:00:18.6: Adding to iommu group 11 [ 0.330136] pci 0000:00:18.7: Adding to iommu group 11 [ 0.330205] pci 0000:01:00.0: Adding to iommu group 12 [ 0.330236] pci 0000:01:00.1: Adding to iommu group 12 [ 0.330267] pci 0000:01:00.2: Adding to iommu group 12 [ 0.330282] pci 0000:02:00.0: Adding to iommu group 12 [ 0.330294] pci 0000:02:01.0: Adding to iommu group 12 [ 0.330306] pci 0000:02:02.0: Adding to iommu group 12 [ 0.330324] pci 0000:02:03.0: Adding to iommu group 12 [ 0.330337] pci 0000:02:04.0: Adding to iommu group 12 [ 0.330350] pci 0000:02:09.0: Adding to iommu group 12 [ 0.330363] pci 0000:03:00.0: Adding to iommu group 12 [ 0.330375] pci 0000:06:00.0: Adding to iommu group 12 [ 0.330387] pci 0000:07:00.0: Adding to iommu group 12 [ 0.330399] pci 0000:07:00.1: Adding to iommu group 12 [ 0.330412] pci 0000:08:00.0: Adding to iommu group 12 [ 0.330441] pci 0000:09:00.0: Adding to iommu group 13 [ 0.330472] pci 0000:0a:00.0: Adding to iommu group 14 [ 0.330510] pci 0000:0b:00.0: Adding to iommu group 15 [ 0.330543] pci 0000:0b:00.1: Adding to iommu group 16 [ 0.330574] pci 0000:0c:00.0: Adding to iommu group 17 [ 0.330604] pci 0000:0c:00.2: Adding to iommu group 18 [ 0.330634] pci 0000:0c:00.3: Adding to iommu group 19 [ 0.330665] pci 0000:0d:00.0: Adding to iommu group 20 [ 0.330695] pci 0000:0d:00.2: Adding to iommu group 21 [ 0.330728] pci 0000:0d:00.3: Adding to iommu group 22 [ 0.333872] AMD-Vi: Extended features (0xf77ef22294ada, 0x0): PPR NX GT IA GA PC GA_vAPIC [ 0.333899] AMD-Vi: Interrupt remapping enabled [ 0.334089] AMD-Vi: Virtual APIC enabled [ 0.334189] perf/amd_iommu: Detected AMD IOMMU #0 (2 banks, 4 counters/bank). ls /sys/kernel/iommu_groups/ 想定される出力例 0 1 10 11 12 13 14 15 16 17 18 19 2 20 21 22 3 4 5 6 7 8 9  ls で番号のディレクトリが表示されれば、IOMMU は有効です。 6.3.3 IOMMU グループの確認  パススルーする GPU の IOMMU グループを確認します。6.3.1項 で控えた映像機能と音声機能の PCI ID を IDS に指定すると、それぞれが属するグループと、そのグループのデバイスだけが表示されます。 IDS="1002:xxxx 1002:yyyy" # 6.3.1 で控えた映像機能・音声機能の PCI ID groups=$(for id in $IDS; do for dev in $(lspci -D -n -d "$id" | cut -d' ' -f1); do basename "$(readlink /sys/bus/pci/devices/$dev/iommu_group)" done done | sort -un) for g in $groups; do echo "IOMMU group $g:" for d in /sys/kernel/iommu_groups/$g/devices/*; do lspci -nns "${d##*/}" done done 想定される出力例 IOMMU group 15: 0b:00.0 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Navi 21 [Radeon RX 6800/6800 XT / 6900 XT] [1002:xxxx] (rev c1) IOMMU group 16: 0b:00.1 Audio device [0403]: Advanced Micro Devices, Inc. [AMD/ATI] Navi 21/23 HDMI/DP Audio Controller [1002:yyyy]  表示されたグループが1つで、映像機能と音声機能の両方が含まれていれば、同じグループです。グループが2つに分かれて表示されれば、別のグループです。同じグループに GPU の機能以外のデバイス(PCIe のブリッジを除く)があると、それも一緒にホストOSのドライバから切り離し、vfio-pci にバインドする必要があります。VFIO は、グループ内のすべてのデバイスが準備できて初めて、そのグループを使えるためです。仮想マシンに渡すかどうかは別の話です。  今回のケースでは、映像機能と音声機能が別のグループに分かれています。 6.3.4 映像出力優先設定の確認  ホストOS用の GPU が起動時の表示に使われていることを確認します。PCI アドレス 07:00.0 はホストOS用の GPU、0b:00.0 はパススルーする GPU です(6.3.1項 の例)。/sys 配下のパスでは、先頭にドメイン番号 0000: を付けます。  以下のコマンドでホストOS用の GPU が 1、パススルーする GPU が 0 であれば成功です。パススルーする GPU が 1 の場合は、6.2節 の設定を見直します。 ホストOS用の GPU(GT 710) cat /sys/bus/pci/devices/0000:07:00.0/boot_vga 想定される出力例 1 パススルーする GPU(RX 6800 XT) cat /sys/bus/pci/devices/0000:0b:00.0/boot_vga 想定される出力例 0 7. OS・カーネル・ドライバの設定 7.1 カーネルパラメータの設定  次のカーネルパラメータは、必要な場合だけ設定します。 iommu=pt: ホストOS自身のデバイスの DMA 変換を省いて、性能の低下を避ける。必須ではない。その代わり、ホストOS側のデバイスの DMA は、IOMMU による変換と制限を受けなくなる 現在のgrub設定(GRUB_CMDLINE_LINUX)を確認 cat /etc/default/grub | grep GRUB_CMDLINE_LINUX GRUB_CMDLINE_LINUX_DEFAULT="" GRUB_CMDLINE_LINUX="" GRUB設定のGRUB_CMDLINE_LINUXを編集 sudo vi /etc/default/grub  GRUB_CMDLINE_LINUXに iommu=pt を追加します。iommu=pt を末尾に追加するので、既存設定は変更しないようにしてください。 - GRUB_CMDLINE_LINUX="" - GRUB_CMDLINE_LINUX="iommu=pt"  次に、変更したGRUB設定を反映します。 sudo update-grub 想定される出力例 Sourcing file `/etc/default/grub' Sourcing file `/etc/default/grub.d/kdump-tools.cfg' Generating grub configuration file ... Found linux image: /boot/vmlinuz-7.0.0-42-generic Found initrd image: /boot/initrd.img-7.0.0-42-generic Found linux image: /boot/vmlinuz-7.0.0-38-generic Found initrd image: /boot/initrd.img-7.0.0-38-generic Warning: os-prober will not be executed to detect other bootable partitions. Systems on them will not be added to the GRUB boot configuration. Check GRUB_DISABLE_OS_PROBER documentation entry. Adding boot menu entry for UEFI Firmware Settings ... done 再起動 sudo reboot  再起動して、設定したカーネルパラメータが反映されていることを確認します。 1. カーネルに渡された起動パラメータの確認 cat /proc/cmdline 想定される出力例(iommu=ptが含まれていればok) BOOT_IMAGE=/vmlinuz-7.0.0-42-generic root=/dev/mapper/ubuntu--vg-ubuntu--lv ro iommu=pt 2. カーネルが実際に採用した IOMMU の動作モードの確認 sudo dmesg | grep "Default domain type" 想定される出力例(Passthroughと表示されればok。"(set via kernel command line)" は、起動パラメータで指定されたことを示す) [ 0.282301] iommu: Default domain type: Passthrough (set via kernel command line) 3. IOMMU グループごとの動作モードの確認(identity は、デバイスのアドレス変換をしないモード) cat /sys/kernel/iommu_groups/*/type | sort | uniq -c 想定される出力例(すべてのグループがidentityと表示されればok。先頭の数字はグループ数) 23 identity 7.2 VFIO モジュールのロード設定  VFIO(vfio-pci)は、デバイスをホストOSのドライバから切り離し、仮想マシンに渡すためのドライバです。1つのデバイスを持てるドライバは1つだけなので、ホストOSの amdgpu が先に GPU を持つと、渡せません。そのため、amdgpu より先に vfio-pci に GPU を持たせます。  まず、変更前の状態を確認します。パススルーする GPU の映像機能と音声機能を、ホストOSのドライバが担当していること、vfio-pci の設定がまだないことを確認します。0b:00 は 6.3.1項 の例です。 1. GPU を現在担当しているドライバの確認(変更前は、ホストOSのドライバが担当している) lspci -nnk -s 0b:00 想定される出力例(Kernel driver in use が amdgpu と snd_hda_intel になっていればok) 0b:00.0 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Navi 21 [Radeon RX 6800/6800 XT / 6900 XT] [1002:xxxx] (rev c1) Subsystem: Sapphire Technology Limited Device [1da2:xxxx] Kernel driver in use: amdgpu Kernel modules: amdgpu 0b:00.1 Audio device [0403]: Advanced Micro Devices, Inc. [AMD/ATI] Navi 21/23 HDMI/DP Audio Controller [1002:yyyy] Subsystem: Advanced Micro Devices, Inc. [AMD/ATI] Navi 21/23 HDMI/DP Audio Controller [1002:yyyy] Kernel driver in use: snd_hda_intel Kernel modules: snd_hda_intel 2. vfio-pci の設定ファイルがまだないことの確認 ls /etc/modprobe.d/vfio.conf 想定される出力例(なにも設定していなければファイルはないです。設定していればファイル名が表示されます。内容は cat で確認できます) ls: cannot access '/etc/modprobe.d/vfio.conf': No such file or directory 3. initramfs に vfio が含まれていないことの確認 sudo lsinitramfs /boot/initrd.img-$(uname -r) | grep vfio 想定される出力例(上記のコマンドでvfio.confがないため、このコマンドでは何も表示されません)  次に、vfio-pci の設定を追加します。  まず、vfio-pci に GPU を担当させる設定を追加します。この設定で、GPU は vfio-pci が担当します。NVIDIA製のGPUは設定が異なるため、注意が必要です。 sudo vi /etc/modprobe.d/vfio.conf ids: vfio-pci に持たせるデバイスの PCI ID。6.3.1項 で控えた全ての機能の PCI ID を書く softdep ... pre: vfio-pci: 指定したドライバ(amdgpu など)より先に vfio-pci を優先的に読み込ませる。今回は、GPU の映像機能と音声機能を担当する amdgpu、radeon、snd_hda_intel に設定する options vfio-pci ids=1002:xxxx,1002:yyyy softdep amdgpu pre: vfio-pci softdep radeon pre: vfio-pci softdep snd_hda_intel pre: vfio-pci  さらに、vfio-pci を起動の早い段階で読み込ませるため、initramfs に含めます。/etc/initramfs-tools/modulesを編集します。 sudo vi /etc/initramfs-tools/modules  /etc/initramfs-tools/modulesに以下の内容を追加します。 vfio_pci vfio_iommu_type1 initramfs の更新 sudo update-initramfs -u 想定される出力例 update-initramfs: Generating /boot/initrd.img-7.0.0-42-generic 再起動 sudo reboot  上の設定を変えたときは、update-initramfs -u を実行し直します。 7.3 GPU の VFIO バインド確認  再起動後、GPU が VFIO に割り当てられていることを確認します。  以下のコマンドで出力されるパススルーをする GPU の全ての機能が Kernel driver in use: vfio-pci になっていること、ホストOS用の GPU(NVIDIA) が Kernel driver in use: nouveau になっていることを確認します。  vfio-pci にならない機能がある場合は、そこに表示されたドライバを調べ、softdep <ドライバ> pre: vfio-pci を vfio.conf に追加してください。 lspci -nnk | grep -A3 -i -E "vga|3d|audio" 想定される出力例(対象GPUのkernelがvfio-pciになっていること) 07:00.0 VGA compatible controller [0300]: NVIDIA Corporation GK208B [GeForce GT 710] [10de:xxxx] (rev a1) Subsystem: Micro-Star International Co., Ltd. [MSI] Device [1462:yyyy] Kernel driver in use: nouveau Kernel modules: nvidiafb, nouveau 07:00.1 Audio device [0403]: NVIDIA Corporation GK208 HDMI/DP Audio Controller [10de:xxxx] (rev a1) Subsystem: Micro-Star International Co., Ltd. [MSI] Device [1462:yyyy] Kernel driver in use: snd_hda_intel Kernel modules: snd_hda_intel 0b:00.0 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Navi 21 [Radeon RX 6800/6800 XT / 6900 XT] [1002:xxxx] (rev c1) Subsystem: Sapphire Technology Limited Device [1da2:zzzz] Kernel driver in use: vfio-pci Kernel modules: amdgpu 0b:00.1 Audio device [0403]: Advanced Micro Devices, Inc. [AMD/ATI] Navi 21/23 HDMI/DP Audio Controller [1002:yyyy] Subsystem: Advanced Micro Devices, Inc. [AMD/ATI] Navi 21/23 HDMI/DP Audio Controller [1002:yyyy] Kernel driver in use: vfio-pci Kernel modules: snd_hda_intel initramfs に vfio.conf が含まれていることを確認する sudo lsinitramfs /boot/initrd.img-$(uname -r) | grep vfio 想定される出力例(etc/modprobe.d/vfio.confが表示されること) etc/modprobe.d/vfio.conf 8. 仮想マシンへの GPU の割り当て  最後に、仮想マシンへ GPU を割り当てます。  仮想マシンに GPU を割り当てる方法は、仮想マシンの作成時に指定する方法と作成済みの仮想マシンに追加する方法の2つです。 ! 今回の環境では仮想マシン作成時に GPU を割り当てる方式では GPU を認識しているがコンソールが出ない現象が起こっています。 そのため、この記事では、作成済みの仮想マシンに GPU を追加する方法のみを記載します。 ! この記事では、KVMをインストールしてある前提で記載します。そのため、KVMのインストールは別記事を参照してください。 8.1 仮想マシンの設定  libvirt は、KVM の仮想マシンを管理する仕組みです。作成済みの仮想マシンに GPU を割り当てるには、仮想マシンを次の設定で作成しておくことを推奨します。 マシンタイプを q35 にする。virt-install では --machine q35。 UEFI(OVMF)で起動する。virt-install では --boot uefi。libvirt が UEFI のファームウェアを認識している必要がある。  次のコマンドは、GPU を付けずに仮想マシンを作成する例です。--hostdev は指定せず、値は環境に合わせて変更してください。  --machine q35 と --boot uefi が、上記の設定にあたります。  --os-variant は、使用する OS の種類を指定する値です。今回は、ubuntu26.04 が候補になかったため、近い ubuntu24.04 を指定しました。 sudo virt-install \ --name local_llm01 \ --memory 8192 \ --vcpus 4 \ --cpu host-passthrough \ --machine q35 \ --boot uefi \ --disk path=/kvm/img/local_llm01.qcow2,size=100,format=qcow2,bus=virtio \ --network bridge=br0,model=virtio \ --graphics none \ --console pty,target_type=serial \ --os-variant ubuntu24.04 \ --location /kvm/iso/ubuntu-26.04.1-live-server-amd64.iso,kernel=casper/vmlinuz,initrd=casper/initrd \ --extra-args 'console=ttyS0,115200n8 serial' 8.2 作成済みの仮想マシンに割り当てる  8.1節で作成した仮想マシンに、GPU を割り当てます。仮想マシンの定義(XML)の <devices> の中に、hostdev を追加します。定義は virsh edit <仮想マシン名> で開きます。  hostdev は、次の位置に、次の書式で書きます。< > の部分が、環境ごとに変わる値です。以下に記入例を記載します。 <domain type='kvm'> ... <devices> ... <hostdev mode='subsystem' type='pci' managed='yes'> <source> <address domain='0x<ドメイン>' bus='0x<バス>' slot='0x<スロット>' function='0x<ファンクション>'/> </source> </hostdev> </devices> </domain>  PCI アドレスは、本来は「ドメイン:バス:スロット.ファンクション」の4つの番号です。ファンクションは GPU の機能(映像機能、音声機能)ごとの番号で、ドメインは lspci では省略されますが、通常は 0000 です。lspci の先頭に表示される バス:スロット.ファンクション(6.3.1項)の各値に、0x を付けて書きます。  GPU の機能ごとに hostdev を1つ追加します。映像機能は必須です。音声機能など、ほかの機能は、仮想マシンで使う場合だけ追加します(6.3.1.2)。  6.3.1項 で確認した、今回の GPU の PCI アドレスは、次のとおりです。 機能 lspci のアドレス domain bus slot function 映像 0b:00.0 0x0000 0x0b 0x00 0x0 音声 0b:00.1 0x0000 0x0b 0x00 0x1  映像機能と音声機能を追加する場合は、次のようになります。 <domain type='kvm'> ... <devices> ... <hostdev mode='subsystem' type='pci' managed='yes'> <source> <address domain='0x0000' bus='0x0b' slot='0x00' function='0x0'/> </source> </hostdev> <hostdev mode='subsystem' type='pci' managed='yes'> <source> <address domain='0x0000' bus='0x0b' slot='0x00' function='0x1'/> </source> </hostdev> </devices> </domain>  1つ目が映像機能、2つ目が音声機能です。音声機能を渡さない場合は、2つ目の hostdev は不要です。 8.3 割り当て後の確認  仮想マシンの定義に hostdev が入っていることを、virsh dumpxml で確認します。 ホストOSで実行 仮想マシンに割り当てた GPU の確認 virsh dumpxml <仮想マシン名> | grep -A6 "<hostdev" 想定される出力例 <hostdev mode='subsystem' type='pci' managed='yes'> <driver name='vfio'/> <source> <address domain='0x0000' bus='0x0b' slot='0x00' function='0x0'/> </source> <alias name='hostdev0'/> <address type='pci' domain='0x0000' bus='0x07' slot='0x00' function='0x0'/> -- <hostdev mode='subsystem' type='pci' managed='yes'> <driver name='vfio'/> <source> <address domain='0x0000' bus='0x0b' slot='0x00' function='0x1'/> </source> <alias name='hostdev1'/> <address type='pci' domain='0x0000' bus='0x08' slot='0x00' function='0x0'/>  停止している仮想マシンは virsh start <仮想マシン名> で起動し、ゲストOSで lspci を実行して、GPU が認識されていることを確認します。 ゲストOSで実行 lspci -nnk | grep -A3 -i -E "vga|display|audio" 想定される出力例(映像機能の Kernel driver in use が amdgpu になっていればok) 音声機能(08:00.0)の行も表示される 07:00.0 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Navi 21 [Radeon RX 6800/6800 XT / 6900 XT] [1002:73bf] (rev c1) Subsystem: Sapphire Technology Limited Device [1da2:e438] Kernel driver in use: amdgpu Kernel modules: amdgpu 08:00.0 Audio device [0403]: Advanced Micro Devices, Inc. [AMD/ATI] Navi 21/23 HDMI/DP Audio Controller [1002:ab28] Subsystem: Advanced Micro Devices, Inc. [AMD/ATI] Navi 21/23 HDMI/DP Audio Controller [1002:ab28] Kernel driver in use: snd_hda_intel Kernel modules: snd_hda_intel  続けて、amdgpu の初期化時にエラーが出ることがあるため、エラーが出ていないことを確認します。 ゲストOSで実行 gpu関連のエラーがないか確認 sudo dmesg | grep -i amdgpu | grep -i -E "error|fail|timeout" 想定される出力例(何も表示されなければok)  GPU のモデルによっては、仮想マシンを停止しても GPU が初期化されず、次の起動で使えなくなること(リセットの問題)があります。割り当て後に、仮想マシンの停止と起動を繰り返して確認してください。 9. まとめ  ここまでで、仮想化基盤(KVM)の仮想マシンに GPU を割り当てる方法と手順を整理しました。今回はAMDのCPU、GPU を使用した手順を書きました。IntelのCPU、NVIDIAのGPUでも同じような設定が必要になりますが、細かいところが異なるうえ、この記事では確認していません。環境に合わせて調べてください。  1章の前書きにも書きましたが、ゲストOSでの ROCm の導入や、ローカル LLM の実行は、この記事では扱っていません。  余談ですが、最近のAIは本当に便利ですね。昔個人用に作った資料だけではパススルーすることができず、AIに質問しながら調査した結果、記事を作ることができました。  ここまで読んでいただき、ありがとうございました。 参考文献 Linux kernel: Dynamic DMA mapping Guide Linux kernel: VFIO - “Virtual Function I/O” RISC-VのIOMMUの仕組み (1. 概要) - FPGA開発日記 3.4. 仮想化されたハードウェアデバイス ACRN Hypervisor: VT-d(DMA remapping)の設計 ArchWiki: PCI passthrough via OVMF(Enabling IOMMU) AI およびグラフィックス向け仮想 GPU ソリューション NVIDIA 仮想 GPU ソリューション - 購入方法 Getting started with Virtualization - Instinct™ Docs - AMD Linux kernel: The kernel’s command-line parameters Linux kernel: drivers/iommu/intel/Kconfig(INTEL_IOMMU_DEFAULT_ON) Ubuntu kernel (resolute): debian.master/config/annotations LKML: x86/cpu: clear SVM feature if disabled by BIOS LKML: Intel IOMMU Pass Through Support NVIDIA 仮想化向けグラフィックス カード NVIDIA AI Enterprise: NVIDIA vGPU (C-Series) NVIDIA: vGPUs and CUDA QEMU: virtio-gpu ROCm: Running ROCm Docker containers Platform9: GPU VM compatibility ROCm: ROCm 10.1.0 compatibility matrix Mesa: Virtio-GPU Venus

  2. Hacker News · · on WTF Ubuntu? · tkinom · torvalds/linux

    Asked claude/haiku5.5 to review that cve against my server, docker images. Claude had passwordless ssh access to that server and no root access. It did the review, confirm that server has the volubility, asked me to ran a few sudo commands, give it the output. It asked me to run a command to disable mptcp option. I then asked it to do complete cve reviews on the host server (U 26.04 was installed a few weeks back) and docker images on that server and update the security review and added a task to do daily check on ubuntu website on kernel security update. EDIT: Just asked claude if it can write a patch and build a image on top and fixed the issue on my server. It said it can. And point out that it can apply the 2 lines patches github.com/torvalds/linux/commit/e3f33b0.patch and build a kernel image on this issue for me. FYI....

  3. FRDM i.MX95 - zephyr rtosを使用してみる。(hello worldの実行, イーサネットの利用, SDカードの利用) FRDM i.MX95 - zephyr rtosを使用してみる。(hello worldの実行, イーサネットの利用, SDカードの利用) - はじめに FRDM i.MX95を使用して、zephyr rtosにより、 参照情報を基に以下のことを行った際の記録メモです。 - サンプルアプリケーション hello_worldの実行 - イーサネットの利用 - SDカード(マイクロSDカード)の利用   - 参照情報 FRDM i.MX95はzephyr rtosの公式サポートボードには 現在含まれていませんでしたので、i.MX95 15x15 EVKを参照しています。 - i.MX95 15x15 EVK - i.MX 95 Applications Processor Reference Manual - github.com/torvalds/linux/blob/master/arch/arm64/…   - サンプルアプリケーションの実行 - hello_world(1)- 参照情報(i.MX95 15x15 EVK)に記載のアプリケーションの実行  west build -b imx95_evk_15x15/mimx9596/a55 samples/synchronization この確認では、/dev/sda1がSDカードとなっています。 $ sudo umount /dev/sda1 $ sudo mkfs.vfat -F32 /dev/sda1 fatload mmc 1:1 0xd0000000 zephyr.bin; dcache flush; icache flush; go 0xd0000000 u-boot=> go 0xd0000000 ## Starting application at 0xD0000000 ... *** Booting Zephyr OS build v4.4.0-8011-gb01be6b7b16e *** thread_a: Hello World from cpu 0 on imx95_evk_15x15! thread_b: Hello World from cpu 0 on imx95_evk_15x15! thread_a: Hello World from cpu 0 on imx95_evk_15x15! thread_b: Hello World from cpu 0 on imx95_evk_15x15! thread_a: Hello World from cpu 0 on imx95_evk_15x15! thread_b: Hello World from cpu 0 on imx95_evk_15x15! - hello_worldの実行(2)- samples/hello_worldでの確認 west build -b imx95_evk_15x15/mimx9596/a55 samples/hello_world -p always u-boot=> fatload mmc 1:1 0xd0000000 zephyr.bin; dcache flush; icache flush; go 0xd0000000 49604 bytes read in 4 ms (11.8 MiB/s) ## Starting application at 0xD0000000 ... *** Booting Zephyr OS build v4.4.0-8011-gb01be6b7b16e *** Hello World! imx95_evk_15x15/mimx9596/a55   - イーサネットの利用 PHYデバイスがi.MX95 15x15 EVKとFRDM i.MX95とでは異なっていたので、 以下を変更して確認しています。 &emdio { pinctrl-0 = <&emdio_default>; pinctrl-names = "default"; status = "okay"; phy0: phy@1 { - compatible = "realtek,rtl8211f"; + compatible = "motorcomm,yt8521"; reg = <0x1>; status = "okay"; + motorcomm,rx-delay-sel = <13>; + motorcomm,tx-delay-sel = <13>; }; }; - サンプルアプリケーションの実行 samples/hello_worldを基に変更しています。 samples/hello_worldのprj.confに以下を追加。 CONFIG_EARLY_CONSOLE=y CONFIG_NETWORKING=y CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_MAIN_STACK_SIZE=5200 CONFIG_SHELL_STACK_SIZE=5200 CONFIG_NET_TX_STACK_SIZE=2048 CONFIG_NET_RX_STACK_SIZE=2048 CONFIG_NET_PKT_RX_COUNT=10 CONFIG_NET_PKT_TX_COUNT=10 CONFIG_NET_BUF_RX_COUNT=20 CONFIG_NET_BUF_TX_COUNT=20 CONFIG_NET_MAX_CONTEXTS=10 CONFIG_NET_DHCPV4=y CONFIG_NET_IPV4=y CONFIG_NET_IPV6=n CONFIG_NET_TCP=y CONFIG_NET_LOG=y CONFIG_INIT_STACKS=y CONFIG_NET_SHELL=y CONFIG_NET_STATISTICS=y CONFIG_NET_STATISTICS_PERIODIC_OUTPUT=n CONFIG_HEAP_MEM_POOL_SIZE=1048576 CONFIG_ETHERNET_LOG_LEVEL_DBG=y CONFIG_LOG_MODE_IMMEDIATE=y CONFIG_LOG_DEFAULT_LEVEL=2 CONFIG_PRINTK=y uart:~$ net dhcpv4 client start 1 uart:~$ net iface 1 Default interface: 1 Interface eth0 (0xd0089518) (Ethernet) [1]                                             =================================== Link addr : 00:00:00:01:02:00        MTU       : 1500 Flags     : AUTO_START,IPv4 Device    : ethernet@4cc00000 (0xd0035380) Status    : oper=UP, admin=UP, carrier=ON Ethernet capabilities supported:         RX checksum offload 10 Mbits     100 Mbits         1 Gbits Ethernet PHY device: phy@1 (0xd0035340) Ethernet link speed: 1 Gbits full-duplex IPv4 unicast addresses (max 1): 192.168.128.109/255.255.255.0 DHCP preferred IPv4 multicast addresses (max 2):       224.0.0.1 IPv4 gateway : 192.168.128.1 DHCPv4 lease time : 86400 DHCPv4 renew time : 43200 DHCPv4 server     : 192.168.128.1 DHCPv4 requested  : 192.168.128.109 DHCPv4 state      : bound   DHCPv4 attempts   : 1 DHCPv4 state      : bound uart:~$ net ping 192.168.128.200  PING 192.168.128.200 28 bytes from 192.168.128.200 to 192.168.128.109: icmp_seq=3 ttl=64 time=51.13 ms --- ping statistics --- 3 packets transmitted, 1 received, 66% packet loss rtt min/avg/max = 51.13/51.13/51.13 ms uart:~$ net ping 192.168.128.200  PING 192.168.128.200 28 bytes from 192.168.128.200 to 192.168.128.109: icmp_seq=1 ttl=64 time=70.45 ms 28 bytes from 192.168.128.200 to 192.168.128.109: icmp_seq=2 ttl=64 time=98.31 ms 28 bytes from 192.168.128.200 to 192.168.128.109: icmp_seq=3 ttl=64 time=20.47 ms --- ping statistics --- 3 packets transmitted, 3 received, 0% packet loss rtt min/avg/max = 20.47/63.08/98.31 ms               uart:~$   - SDカード(マイクロSDカード)の利用 変更ファイルに関する差分点、追加内容を以下に示しています。 変更点は、参照情報のリファレンスマニュアル、Linuxの実装を基にしています。 usdhc1についても変更していますが、usdhc1については、eMMCのため実際の動作は未確認です。 - device treeの変更 }; + usdhc1: usdhc@42850000 { + compatible = "nxp,imx-usdhc"; + reg = <0x42850000 0x10000>; + interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL IRQ_DEFAULT_PRIORITY>; + interrupt-parent = <&gic>; + clocks = <&scmi_clk IMX95_CLK_USDHC1>; + max-current-330 = <1020>; + max-current-180 = <1020>; + max-bus-freq = <208000000>; + min-bus-freq = <400000>; + status = "disabled"; + }; + + usdhc2: usdhc@42860000 { + compatible = "nxp,imx-usdhc"; + reg = <0x42860000 0x10000>; + interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL IRQ_DEFAULT_PRIORITY>; + interrupt-parent = <&gic>; + clocks = <&scmi_clk IMX95_CLK_USDHC2>; + max-current-330 = <1020>; + max-current-180 = <1020>; + max-bus-freq = <208000000>; + min-bus-freq = <400000>; + status = "disabled"; + }; + }; drive-strength = "x4"; }; }; + + pinmux_usdhc1: pinmux_usdhc1 { + group0 { + pinmux = <&iomuxc_sd1_clk_usdhc_clk_usdhc1_clk>, + <&iomuxc_sd1_strobe_usdhc_strobe_usdhc1_strobe>; + drive-strength = "x3"; + bias-pull-down; + slew-rate = "fast"; + input-schmitt-enable; + }; + + group1 { + pinmux = <&iomuxc_sd1_cmd_usdhc_cmd_usdhc1_cmd>, + <&iomuxc_sd1_data0_usdhc_data_usdhc1_data0>, + <&iomuxc_sd1_data1_usdhc_data_usdhc1_data1>, + <&iomuxc_sd1_data2_usdhc_data_usdhc1_data2>, + <&iomuxc_sd1_data3_usdhc_data_usdhc1_data3>, + <&iomuxc_sd1_data4_usdhc_data_usdhc1_data4>, + <&iomuxc_sd1_data5_usdhc_data_usdhc1_data5>, + <&iomuxc_sd1_data6_usdhc_data_usdhc1_data6>, + <&iomuxc_sd1_data7_usdhc_data_usdhc1_data7>; + drive-strength = "x3"; + slew-rate = "fast"; + input-schmitt-enable; + bias-pull-up; + input-enable; + }; + }; + + pinmux_usdhc1_100mhz: pinmux_usdhc1_100mhz { + group0 { + pinmux = <&iomuxc_sd1_clk_usdhc_clk_usdhc1_clk>, + <&iomuxc_sd1_strobe_usdhc_strobe_usdhc1_strobe>; + drive-strength = "x3"; + bias-pull-down; + slew-rate = "fast"; + input-schmitt-enable; + }; + + group1 { + pinmux = <&iomuxc_sd1_cmd_usdhc_cmd_usdhc1_cmd>, + <&iomuxc_sd1_data0_usdhc_data_usdhc1_data0>, + <&iomuxc_sd1_data1_usdhc_data_usdhc1_data1>, + <&iomuxc_sd1_data2_usdhc_data_usdhc1_data2>, + <&iomuxc_sd1_data3_usdhc_data_usdhc1_data3>, + <&iomuxc_sd1_data4_usdhc_data_usdhc1_data4>, + <&iomuxc_sd1_data5_usdhc_data_usdhc1_data5>, + <&iomuxc_sd1_data6_usdhc_data_usdhc1_data6>, + <&iomuxc_sd1_data7_usdhc_data_usdhc1_data7>; + drive-strength = "x3"; + slew-rate = "fast"; + input-schmitt-enable; + bias-pull-up; + input-enable; + }; + }; + + pinmux_usdhc1_200mhz: pinmux_usdhc1_200mhz { + group0 { + pinmux = <&iomuxc_sd1_clk_usdhc_clk_usdhc1_clk>, + <&iomuxc_sd1_strobe_usdhc_strobe_usdhc1_strobe>; + drive-strength = "x6"; + bias-pull-down; + slew-rate = "fast"; + input-schmitt-enable; + }; + + group1 { + pinmux = <&iomuxc_sd1_cmd_usdhc_cmd_usdhc1_cmd>, + <&iomuxc_sd1_data0_usdhc_data_usdhc1_data0>, + <&iomuxc_sd1_data1_usdhc_data_usdhc1_data1>, + <&iomuxc_sd1_data2_usdhc_data_usdhc1_data2>, + <&iomuxc_sd1_data3_usdhc_data_usdhc1_data3>, + <&iomuxc_sd1_data4_usdhc_data_usdhc1_data4>, + <&iomuxc_sd1_data5_usdhc_data_usdhc1_data5>, + <&iomuxc_sd1_data6_usdhc_data_usdhc1_data6>, + <&iomuxc_sd1_data7_usdhc_data_usdhc1_data7>; + drive-strength = "x6"; + slew-rate = "fast"; + input-schmitt-enable; + bias-pull-up; + input-enable; + }; + }; + + pinmux_usdhc2: pinmux_usdhc2 { + group0 { + pinmux = <&iomuxc_sd2_clk_usdhc_clk_usdhc2_clk>; + drive-strength = "x3"; + bias-pull-down; + slew-rate = "fast"; + input-schmitt-enable; + }; + + group1 { + pinmux = <&iomuxc_sd2_cmd_usdhc_cmd_usdhc2_cmd>, + <&iomuxc_sd2_data0_usdhc_data_usdhc2_data0>, + <&iomuxc_sd2_data1_usdhc_data_usdhc2_data1>, + <&iomuxc_sd2_data2_usdhc_data_usdhc2_data2>, + <&iomuxc_sd2_data3_usdhc_data_usdhc2_data3>; + drive-strength = "x3"; + slew-rate = "fast"; + input-schmitt-enable; + bias-pull-up; + input-enable; + }; + + group2 { + pinmux = <&iomuxc_sd2_vselect_usdhc_vselect_usdhc2_vselect>; + drive-strength = "x4"; + slew-rate = "slightly_fast"; + }; + + group3 { + pinmux = <&iomuxc_sd2_cd_b_gpio_io_bit_gpio3_io_bit0>, + <&iomuxc_sd2_reset_b_gpio_io_bit_gpio3_io_bit7>; + drive-strength = "x4"; + slew-rate = "slightly_fast"; + bias-pull-up; + }; + }; + + pinmux_usdhc2_100mhz: pinmux_usdhc2_100mhz { + group0 { + pinmux = <&iomuxc_sd2_clk_usdhc_clk_usdhc2_clk>; + drive-strength = "x3"; + bias-pull-down; + slew-rate = "fast"; + input-schmitt-enable; + }; + + group1 { + pinmux = <&iomuxc_sd2_cmd_usdhc_cmd_usdhc2_cmd>, + <&iomuxc_sd2_data0_usdhc_data_usdhc2_data0>, + <&iomuxc_sd2_data1_usdhc_data_usdhc2_data1>, + <&iomuxc_sd2_data2_usdhc_data_usdhc2_data2>, + <&iomuxc_sd2_data3_usdhc_data_usdhc2_data3>; + drive-strength = "x3"; + slew-rate = "fast"; + input-schmitt-enable; + bias-pull-up; + input-enable; + }; + + group2 { + pinmux = <&iomuxc_sd2_vselect_usdhc_vselect_usdhc2_vselect>; + drive-strength = "x4"; + slew-rate = "slightly_fast"; + }; + + group3 { + pinmux = <&iomuxc_sd2_cd_b_gpio_io_bit_gpio3_io_bit0>, + <&iomuxc_sd2_reset_b_gpio_io_bit_gpio3_io_bit7>; + drive-strength = "x4"; + slew-rate = "slightly_fast"; + bias-pull-up; + }; + }; + + pinmux_usdhc2_200mhz: pinmux_usdhc2_200mhz { + group0 { + pinmux = <&iomuxc_sd2_clk_usdhc_clk_usdhc2_clk>; + drive-strength = "x3"; + bias-pull-down; + slew-rate = "fast"; + input-schmitt-enable; + }; + + group1 { + pinmux = <&iomuxc_sd2_cmd_usdhc_cmd_usdhc2_cmd>, + <&iomuxc_sd2_data0_usdhc_data_usdhc2_data0>, + <&iomuxc_sd2_data1_usdhc_data_usdhc2_data1>, + <&iomuxc_sd2_data2_usdhc_data_usdhc2_data2>, + <&iomuxc_sd2_data3_usdhc_data_usdhc2_data3>; + drive-strength = "x3"; + slew-rate = "fast"; + input-schmitt-enable; + bias-pull-up; + input-enable; + }; + + group2 { + pinmux = <&iomuxc_sd2_vselect_usdhc_vselect_usdhc2_vselect>; + drive-strength = "x4"; + slew-rate = "slightly_fast"; + }; + + group3 { + pinmux = <&iomuxc_sd2_cd_b_gpio_io_bit_gpio3_io_bit0>, + <&iomuxc_sd2_reset_b_gpio_io_bit_gpio3_io_bit7>; + drive-strength = "x4"; + slew-rate = "slightly_fast"; + bias-pull-up; + }; + }; + }; phy-connection-type = "rgmii"; status = "okay"; }; + +&usdhc1 { + pinctrl-0 = <&pinmux_usdhc1>; + pinctrl-1 = <&pinmux_usdhc1_100mhz>; + pinctrl-2 = <&pinmux_usdhc1_200mhz>; + pinctrl-names = "default", "med", "fast"; + mmc-hs200-1_8v; + mmc-hs400-1_8v; + read-watermark = <0x10>; + write-watermark = <0x80>; + status = "disabled"; + + sdmmc { + compatible = "zephyr,mmc-disk"; + disk-name = "SD2"; + status = "disabled"; + }; +}; + +&gpio3 { + status = "okay"; +}; + +&usdhc2 { + pinctrl-0 = <&pinmux_usdhc2>; + pinctrl-1 = <&pinmux_usdhc2_100mhz>; + pinctrl-2 = <&pinmux_usdhc2_200mhz>; + pinctrl-names = "default", "med", "fast"; + pwr-gpios = <&gpio3 7 GPIO_ACTIVE_HIGH>; + cd-gpios = <&gpio3 0 GPIO_ACTIVE_LOW>; + power-delay-ms = <20>; + mmc-hs200-1_8v; + mmc-hs400-1_8v; + read-watermark = <0x10>; + write-watermark = <0x80>; + status = "okay"; + + sdmmc { + compatible = "zephyr,sdmmc-disk"; + disk-name = "SD"; + status = "okay"; + }; +}; - driverの変更 static int imx_usdhc_init(const struct device *dev) { host_config.readWatermarkLevel = cfg->read_watermark; host_config.writeWatermarkLevel = cfg->write_watermark; USDHC_Init(base, &host_config); + /* Zephyr側の初期値(1ビット)に、コントローラのバス幅を合わせる */ + USDHC_SetDataBusWidth(base, kUSDHC_DataBusWidth1Bit); + /* U-Boot が UHS で残した VSELECT(1.8V)を、host_io の初期値(3.3V)に合わせる */ + imx_usdhc_select_1_8v(base, false); /* Read host controller properties */ imx_usdhc_init_host_props(dev); /* Set power GPIO low, so card starts powered off */ if (cfg->pwr_gpio.port) { ret = gpio_pin_configure_dt(&cfg->pwr_gpio, GPIO_OUTPUT_INACTIVE); if (ret) { return ret; } + /* UHS(1.8V)状態のカードが確実にリセットされるよう、電源OFFを保持 */ + k_busy_wait(100 * USEC_PER_MSEC); } else { - modules/hal_nxp/mcuxに関する対応 +#ifndef USDHC_COMPAT_H +#define USDHC_COMPAT_H +#ifndef __ASSEMBLER__ +#include "fsl_device_registers.h" +#include "PERI_USDHC.h" +#define USDHC1_BASE (0x42850000u) +#define USDHC2_BASE (0x42860000u) +#define USDHC3_BASE (0x428B0000u) +#define USDHC1 ((USDHC_Type *)USDHC1_BASE) +#define USDHC2 ((USDHC_Type *)USDHC2_BASE) +#define USDHC3 ((USDHC_Type *)USDHC3_BASE) +#define USDHC_BASE_ADDRS { 0u, USDHC1_BASE, USDHC2_BASE, USDHC3_BASE } +#define USDHC_BASE_PTRS { (USDHC_Type *)0u, USDHC1, USDHC2, USDHC3 } +#define USDHC_IRQS { (IRQn_Type)0, (IRQn_Type)86, (IRQn_Type)87, (IRQn_Type)0 } + +//#define FSL_FEATURE_SOC_USDHC_COUNT (3) + +//#define FSL_FEATURE_USDHC_HAS_EXT_DMA (0) +/* @brief Has HS400 mode (MIX_CTRL[HS400_MODE]) */ +//#define FSL_FEATURE_USDHC_HAS_HS400_MODE (1) +/* @brief Has SDR50 support (HOST_CTRL_CAP[SDR50_SUPPORT]) */ +#define FSL_FEATURE_USDHC_HAS_SDR50_MODE (1) +/* @brief Has SDR104 support (HOST_CTRL_CAP[SDR104_SUPPORT]) */ +#define FSL_FEATURE_USDHC_HAS_SDR104_MODE (1) +/* @brief USDHC has reset control */ +//#define FSL_FEATURE_USDHC_HAS_RESET (0) +/* @brief USDHC has no bitfield WTMK_LVL[WR_BRST_LEN] and WTMK_LVL[RD_BRST_LEN] */ +#define FSL_FEATURE_USDHC_HAS_NO_RW_BURST_LEN (1) +/* @brief If USDHC instance support 8 bit width */ +//#define FSL_FEATURE_USDHC_INSTANCE_SUPPORT_8_BIT_WIDTHn(x) (1) +/* @brief If USDHC instance support HS400 mode */ +//#define FSL_FEATURE_USDHC_INSTANCE_SUPPORT_HS400_MODEn(x) (0) +/* @brief If USDHC instance support 1v8 signal */ +//#define FSL_FEATURE_USDHC_INSTANCE_SUPPORT_1V8_SIGNALn(x) (1) +/* @brief Has no retuning time counter (HOST_CTRL_CAP[TIME_COUNT_RETURNING]) */ +#define FSL_FEATURE_USDHC_REGISTER_HOST_CTRL_CAP_HAS_NO_RETUNING_TIME_COUNTER (1) +/* @brief Has no VSELECT bit in VEND_SPEC register */ +//#define FSL_FEATURE_USDHC_HAS_NO_VOLTAGE_SELECT (0) +/* @brief Has no VS18 bit in HOST_CTRL_CAP register */ +//#define FSL_FEATURE_USDHC_HAS_NO_VS18 (0) +#endif +#endif - サンプルアプリケーションの変更 samples/hello_worldを基に変更しています。 project(hello_world) +#zephyr_include_directories( +# $ENV{HOME}/dev_env/zephyrproject/modules/hal/nxp/mcux/mcux-sdk-ng/devices/i.MX/i.MX95/periph +# ${CMAKE_CURRENT_LIST_DIR}/src) +#zephyr_compile_options(-include ${CMAKE_CURRENT_LIST_DIR}/src/usdhc_compat.h) + +set(USDHC_COMPAT_HDR ${CMAKE_CURRENT_LIST_DIR}/src/usdhc_compat.h) +set(USDHC_COMPAT_INC + $ENV{HOME}/dev_env/zephyrproject/modules/hal/nxp/mcux/mcux-sdk-ng/devices/i.MX/i.MX95/periph + ${CMAKE_CURRENT_LIST_DIR}/src) + +foreach(tgt drivers__sdhc modules__hal_nxp) + if(TARGET ${tgt}) + target_include_directories(${tgt} PRIVATE ${USDHC_COMPAT_INC}) + target_compile_options(${tgt} PRIVATE "SHELL:-include ${USDHC_COMPAT_HDR}") + endif() +endforeach() + target_sources(app PRIVATE src/main.c) -#include <stdio.h> +#include <zephyr/kernel.h> +#include <zephyr/fs/fs.h> +#include <zephyr/storage/disk_access.h> +#include <ff.h> + +static FATFS fat_fs; +static struct fs_mount_t mp = { + .type = FS_FATFS, + .fs_data = &fat_fs, + .mnt_point = "/SD:", +}; int main(void) { - printf("Hello World! %s\n", CONFIG_BOARD_TARGET); + int rc; + uint32_t sector_count = 0, sector_size = 0; + struct fs_file_t f; + + printk("Hello World! start\n"); + + rc = disk_access_init("SD"); + printk("disk_access_init: %d\n", rc); + if (rc != 0) { + return 0; + } + + rc = disk_access_ioctl("SD", DISK_IOCTL_GET_SECTOR_COUNT, &sector_count); + printk("sector_count: %u (rc=%d)\n", sector_count, rc); + rc = disk_access_ioctl("SD", DISK_IOCTL_GET_SECTOR_SIZE, &sector_size); + printk("sector_size: %u (rc=%d)\n", sector_size, rc); + + rc = fs_mount(&mp); + printk("fs_mount: %d\n", rc); + if (rc != 0) { + return 0; + } + + struct fs_dir_t dir; + struct fs_dirent ent; + + fs_dir_t_init(&dir); + rc = fs_opendir(&dir, "/SD:"); + printk("fs_opendir: %d\n", rc); + while (rc == 0) { + rc = fs_readdir(&dir, &ent); + if (rc != 0 || ent.name[0] == '\0') { + break; + } + printk(" %s %s (%zu)\n", + ent.type == FS_DIR_ENTRY_DIR ? "[DIR]" : "[FILE]", + ent.name, ent.size); + } + fs_closedir(&dir); + + const char *test_path = "/SD:/TEST.TXT"; + const char *write_data = "Zephyr FS Write Test!"; + size_t write_len = strlen(write_data); + char read_buf[64] = {0}; + ssize_t bytes_processed; + + printk("\n--- Write & Verify Test Start ---\n"); + + // 1. ファイルを書き込みモードでオープン + fs_file_t_init(&f); + rc = fs_open(&f, test_path, FS_O_CREATE | FS_O_WRITE); + printk("fs_open (write): %d\n", rc); + + if (rc == 0) { + // データを書き込み + bytes_processed = fs_write(&f, write_data, write_len); + printk("fs_write: %zd bytes written\n", bytes_processed); + + if (bytes_processed != write_len) { + printk("Error: Write length mismatch or error occurred.\n"); + } + + fs_close(&f); + } else { + printk("Error: Failed to open file for writing.\n"); + } + + // 2. 書き込んだファイルを読み込みモードでオープンして確認 + fs_file_t_init(&f); + rc = fs_open(&f, test_path, FS_O_READ); + printk("fs_open (read): %d\n", rc); + + if (rc == 0) { + // データを読み込み + bytes_processed = fs_read(&f, read_buf, sizeof(read_buf) - 1); + printk("fs_read: %zd bytes read\n", bytes_processed); + + if (bytes_processed > 0) { + read_buf[bytes_processed] = '\0'; // 文字列終端処理 + printk("Read Data: \"%s\"\n", read_buf); + + // 元のデータと一致するか比較 + if (bytes_processed == write_len && memcmp(write_data, read_buf, write_len) == 0) { + printk("Verification SUCCESS! Data matches.\n"); + } else { + printk("Verification FAILED! Data mismatch.\n"); + } + } else { + printk("Error: Failed to read data or file is empty.\n"); + } + + fs_close(&f); + } else { + printk("Error: Failed to open file for reading.\n"); + } + printk("--- Write & Verify Test End ---\n\n"); return 0; } + CONFIG_SHELL=y + CONFIG_DISK_ACCESS=y + CONFIG_SDHC=y + CONFIG_DISK_DRIVER_SDMMC=y + CONFIG_FILE_SYSTEM=y + CONFIG_FAT_FILESYSTEM_ELM=y + CONFIG_FILE_SYSTEM_SHELL=y + CONFIG_DCACHE_LINE_SIZE_DETECT=n + CONFIG_DCACHE_LINE_SIZE=64 + CONFIG_GPIO=y + CONFIG_EARLY_CONSOLE=y + CONFIG_LOG=y + CONFIG_LOG_MODE_IMMEDIATE=y u-boot=> fatload mmc 1:1 0xd0000000 zephyr.bin; dcache flush; icache flush; go 0xd0000000 172560 bytes read in 5 ms (32.9 MiB/s) ## Starting application at 0xD0000000 ... [00:00:00.346,000] <inf> sd: Card switched to 1.8V signaling disk_access_init: 0 sector_count: 60440576 (rc=0) sector_size: 512 (rc=0) fs_mount: 0 fs_opendir: 0 [FILE] ZEPHYR.BIN (172560) --- Write & Verify Test Start --- fs_open (write): 0 fs_write: 21 bytes written fs_open (read): 0 fs_read: 21 bytes read Read Data: "Zephyr FS Write Test!" Verification SUCCESS! Data matches. --- Write & Verify Test End ---

  4. But here's the interesting part: he later renamed it "One Giant Leap for Frogkind" during the Linux 3.12 development cycle. Imagine going from a suicidal squirrel to a giant frog in a kernel release. linus tovald moment github.com/torvalds/linux/blob/v3.12-rc1/Makefile t.co

    6 likes · 1 repost · 322 views
  5. Ubuntu and RHEL still have no fixed kernel available Until then, you can drop inbound IPv4 TCP with IP options at the edge and disable MPTCP where unused Obviously, patch hosts with MPTCP listeners first Not in KEV, but race PoCs are already on GitHub Upstream fix: github.com/torvalds/linux/commit/e3f33b0a1d89d738…

    12 likes · 2 reposts
  6. 自作RISC-V rv32imaでLinux(no MMU)をブートしてみる 始めに  コロナ禍の頃から細々と作成、デバッグを続けていたFPGA版32bit RISC-Vですが、とうとうLinux( MMUなしですが )が動作しました。いったんインストール方法等動作させる方法を一気通貫で書いておこうと思い、新規に機序を起こしました。Arty A7 100T限定ですが( 35Tでも動作確認できました!)、お持ちで興味ある方は再現実験などしていただけると嬉しいです。 終盤はデバッグでclaude codeに頼りっぱなしの開発になりましたが、何とかゴールにたどり着いたと思っています。 2026/11/3追記 - Artry A7 35TでもBRAM節約すれば動作することを確認。fpga_top.v のパラメータを以下の画像のように変更してください。 !image.png 必要なもの - Arty A7 100T ( 未確認ですが35TでもキャッシュやスクラッチRAMのサイズを縮小してつかえるかも ) - Vivado - Teraterm (本文では5を使用) - wsl 1. FPGA(Vivado)の環境セットアップ まずはご自分の方法でgitからRTLをクローンします。 ここでは、wslの環境でクローンしています。クローンする場所としては、Windows のVivadoから見えるwindows側のディレクトリにします。( /mnt/c/shareなど) そのままでは、各RTLが複数のディレクトリに分散して扱いずらいので、使用するファイルを一つのディレクトリにコピーします。 git clone https://github.com/yoshiki9636/my-riscv-rv32i-dc cd my-riscv-rv32i-dc mkdir fsim cp buslogics/*.v fsim cp cpu_m/mex_stage.v fsim cp fpga/fpga_top.v fsim cp io/*.v fsim cp mig/*.v fsim cp mon/*.v fsim Vivadoを立ち上げ、Create Projectを選択 !スクリーンショット 2026-11-01 085533.png 適当な場所にワークフォルダを指定(用例ではmy-riscv-rv32i-dc/syn/の下に作成) !image.png RTLプロジェクトを選択 !image.png Add Filesを選択 !image.png 先ほどのRTLディレクトリ(fsim/)に移動して.vファイルをすべて選択 !image.png Next !image.png Add Filesを選択 !image.png syn/riscv_io_pins.xdc を選択 !image.png Next !image.png Searchに XC7A100TCSG324-1 を入力 !image.png 検索されたFPGAを選択しNext !image.png Finish !image.png これでRTLと設定ファイルが読み込めました。 RTLが見えますが、ハードマクロのclockとmigが?になっています。 ここからclockの設定 !image.png Window->IP Catalog を選択 !image.png IP Catalog内のFPGA Features and Desgin->Clocking->Clocking Wizard !image.png Inputタブそのまま(100MHz) Outputタブ clk_out1, clk_out2にチェック clk_out1を200MHz, clk_out2を50MHzに設定 OK !image.png Generate !image.png ここからmigの設定 Window->IP Catalog を選択 Searchに mig と入れて出てきたIPを選択 !image.png 以下、スクショのパラメータを入力(たくさんあります) !image.png !image.png !image.png !image.png !image.png 下の部分 !image.png !image.png !image.png 下の部分 !image.png !image.png !image.png Read XDC/UCF を選択 !image.png syn/Arty_C_mig.ucf を選択 !image.png Validate を選択してOK !image.png Next !image.png !image.png !image.png Accept選択でNext !image.png !image.png Generate !image.png Generate 最後にOK !image.png 合成と配置 Run Implimentationを選択 ⇒ 合成と配置が始まる !image.png ビットストリーム生成 !image.png 生成したビットストリームをFPGAに転送 ※FPGAをPCに接続していること Open Hardware Manager -> Open Target -> AUto Connect !image.png Prograim Device -> そのボードのIDを選択 !image.png .bitファイルが Bitstream file 欄にあることを確認して Program  ⇒ ビットストリームがFPGAに転送される !image.png ここで、Vivadoでの作業は完了 2. Teratermのセットアップ Teraterm を立ち上げ、シリアルポートを選択し OK !image.png 設定 -> 端末 を選択 !image.png 改行コードの受信をAUTOに設定して OK !image.png 設定 -> シリアルポート !image.png スピードを 921600 に設定し、現在の接続を再設定 を選択 !image.png 個の時点で、Teratermのコンソールに文字が打てるはず !image.png これでモニターに入れました。 Ctrl-Cで入力をキャンセルするので、 Ctrl-Cを押した後、 r 00000000 00000080 とやってメモリダンプが出せるはずです。 3. クロスビルド環境の構築 すでにRISC-Vのビルド環境がある人は飛ばしてください。 以下の記事の通りにするとlinux向けのビルド環境が整います。 blog.n-hassy.info git clone https://github.com/riscv/riscv-gnu-toolchain mkdir build cd build ../configure --prefix=/opt/riscv32ima --with-arch=rv32ima --with-abi=ilp32d make linux -j$(nproc) .bashrcにパスを通してください。 export PATH=/opt/riscv32ima/bin:$PATH で source ~/.bashrc 4. Linux実行バイナリのコンパイル WSL上で本CPU向けの環境をクローン git clone https://github.com/yoshiki9636/linux_for_my-riscv-rv32i-dc cd linux_for_my-riscv-rv32i-dc linuxをひっぱってくる mkdir linux cd linux git init git remote add origin https://github.com/torvalds/linux.git git fetch --depth 1 origin cbfffcca2bf0622b601b7eaf477aa29035169184 git checkout FETCH_HEAD 上記が重くて反応が悪い場合の代替URL (1) kernel.org 本家(GitHub 版の元リポジトリ) git remote add origin https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git (2) Google のミラー(速くて安定していることが多い) git remote add origin https://kernel.googlesource.com/pub/scm/linux/kernel/git/torvalds/linux (3) kernel.org の git プロトコル版(HTTPS が通らない環境向け、ポート 9418) git remote add origin git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 次に差分を当てます。 git apply ../fpga-kernel.patch cp ../fpga.config .config カーネル等をビルドします。 ※PATHの中に/opt/riscv32ima/binが通っていることを確認しておいてください make ARCH=riscv CROSS_COMPILE=riscv32-unknown-linux-gnu- olddefconfig make ARCH=riscv CROSS_COMPILE=riscv32-unknown-linux-gnu- -j$(nproc) make ARCH=riscv CROSS_COMPILE=riscv32-unknown-linux-gnu- dtbs -> vmlinux、System.map、arch/riscv/boot/Image、usr/gen_init_cpio ができます。 次にブートスタブ作成 cd ../start/ riscv32-unknown-linux-gnu-gcc -march=rv32ima -mabi=ilp32 -c start.S -ostart.o riscv32-unknown-linux-gnu-ld -T start.ld start.o -o start.elf 次にinitramfsを作成(busybox等) cd ../initramfs/ git clone https://git.busybox.net/busybox cd busybox git checkout 1_36_1 cp ../busybox.config .config make oldconfig make CFLAGS_busybox="-static-pie -Wl,-z,norelro" -j$(nproc) make busybox.links cd .. これでbusybox(約 1.27 MB)と、アプレット一覧(78 行)ができる mtest(検証に使用していた独自アプリ)のビルド riscv32-unknown-linux-gnu-gcc -O2 -fPIE -static-pie -Wl,-z,norelro -o mtest $R/initramfs/mtest.c riscv32-unknown-linux-gnu-strip mtest gen_init_cpio 用のリストを手動作成 vi等で以下の内容のファイル initramfs.list を作成 dir /dev 0755 0 0 nod /dev/console 0600 0 0 c 5 1 nod /dev/null 0666 0 0 c 1 3 nod /dev/ttyMY0 0600 0 0 c 4 64 dir /proc 0755 0 0 dir /sys 0755 0 0 dir /tmp 0755 0 0 dir /etc 0755 0 0 dir /sbin 0755 0 0 dir /bin 0755 0 0 dir /usr 0755 0 0 dir /usr/bin 0755 0 0 file /bin/busybox busybox/busybox 0755 0 0 file /bin/mtest mtest 0755 0 0 file /init init 0755 0 0 エディタを閉じて以下を実行 for a in $(sed 's|.*/||' busybox/busybox.links); do echo "slink /bin/$a busybox 0777 0 0"; done >> initramfs.list initramfs.cpioを作成 ../linux/usr/gen_init_cpio initramfs.list > initramfs.cpio 中身を確認してトップに置く cpio -itv < initramfs.cpio | less cp initramfs.cpio ../ cd .. FPGA向けイメージ作成 python3 $R/make_image_reloc.py 出来上がったImage.hexがFPGA向けのダンプファイル ⇒ windowsから見える(/mnt/c/share/など)に転送する 5. FPGA上で実行 先ほど開いたTereterm端末上で以下のコマンドをうつ Ctrl-cの後 w 000000 その後、 ファイル->ファイル送信 !image.png ファイル選択を選択して先ほどのImage.hexを選択、OKを押す !image.png アップロードが開始されます。5分ほどかかります。 終了したら、Ctrl-Cを押したのち、 g 00000000 で起動します。 Linuxコンソールが出れば成功です。 !image.png お疲れ様でした! 最後に スクショだらけでやたら長くなってしまいました。覚えてしまうとそれほど大変ではないのですが、他人に説明するのは大変だと改めて実感いたしました。もし、追試などやってもらえたら光栄です。

  7. nginxのupstream_connect_timeが1秒刻みになる nginx 側のレイテンシのアラートが鳴ったのに、nginx の後ろのアプリケーションサーバーのログやメトリクスでは、同じリクエストが速く終わっていることがある。アプリケーションサーバーが full GC などでプロセスごと数秒止まり1、その間に届いた接続が待たされると、こうなる。 捨てられた SYN は 1 秒ごとに送り直され、アプリケーションサーバーが動き出したあとにつながる。nginx からは、接続を張るのに約 1 秒、約 2 秒、約 3 秒かかった 200 に見える。下の3行は nginx のアクセスログで、$upstream_connect_time(nginx がアプリケーションサーバーへの接続を張り終えるまでにかかった秒数)を uct として出している。列は時刻、リクエスト ID、ステータス、uct、$upstream_header_time(uht)、$upstream_response_time(urt)、$request_time(rt)の順に並ぶ。uht と urt は、nginx がアプリケーションサーバーにつなぎ始めてから、応答の先頭を受け取るまでと、応答を受け取り終えるまでの秒数だ。rt は、nginx がリクエストを受けてから応答を返し終えるまでの秒数だ。 1792402370.463 487aefe88a1328206a8e93c7c242399a 200 uct=1.002 uht=1.002 urt=1.002 rt=1.002 1792402370.464 cfdd11ceca67677e3601df796850a712 200 uct=2.067 uht=2.067 urt=2.067 rt=2.068 1792402371.040 dd774240d10448d9dc41bfcaaa7d8dfe 200 uct=3.054 uht=3.055 urt=3.055 rt=3.054 アプリケーションサーバーには、nginx が付けたリクエスト ID を渡し、ログに時刻、リクエスト ID、処理時間(ミリ秒)の順に出している。上の3行と同じリクエスト ID の行は次のとおりだ。 1792402370.463 487aefe88a1328206a8e93c7c242399a 0.092 1792402370.463 cfdd11ceca67677e3601df796850a712 0.104 1792402371.040 dd774240d10448d9dc41bfcaaa7d8dfe 0.084 かかった時間のほとんどが接続を張るまでの時間で、アプリケーションサーバーでの処理は 0.1 ミリ秒ほどだ。アプリケーションサーバーが時間を測り始めるのは接続を取り出したあとなので、接続を張るまでの待ちは、そのログやメトリクスに出ない。 上のログは毎秒 200 件を受けるアプリケーションサーバーを 3 秒止めて取ったものだ2。 何が起きているか アプリケーションサーバーが止まると accept キューが埋まり、そのあと届いた SYN は捨てられ、nginx 側のカーネルの再送でつながる。 accept キュー TCP の接続を張るやりとり(ハンドシェイク)は、カーネルが行う。接続を張る側が接続を求める SYN を送り、受ける側が受け入れの返事の SYN-ACK を返し、張る側が ACK を返すと、ハンドシェイクが終わる。終わった接続は、サーバーのプロセスが accept というシステムコールで取り出すまで、カーネルの accept キューに並んで待つ。 アプリケーションサーバーが止まっていても、アプリケーションサーバー側のカーネルはハンドシェイクを進め、終わった接続をキューに積む。止まっている間は接続が取り出されないので、キューは埋まっていく。 キューに並べられる接続の数の上限が backlog で、アプリケーションサーバーが接続を待ち受けるとき(listen するとき)に backlog をカーネルに渡す。値はランタイムやフレームワークの既定値か設定で決まる。 満杯なら SYN を捨てる キューにある接続の数が backlog を超えると、アプリケーションサーバー側のカーネルは、新しく届いた SYN を返事をせずに捨てる3。 再送でつながる SYN に返事がないと、nginx 側のカーネルは時間をおいて SYN を送り直す。これを SYN の再送と呼ぶ。nginx 側のカーネルが Linux 6.5 以降なら、最初の数回を 1 秒間隔で送り直す4。 送り直した SYN も、キューが満杯のうちは捨てられる。アプリケーションサーバーが動き出してキューが空くと、その次の再送で SYN-ACK が返り、つながる。何回目の再送でつながったかで、$upstream_connect_time は約 1 秒、約 2 秒、約 3 秒になる。冒頭の3行がこれにあたる。 検証 アプリケーションサーバーを 3 秒止めて、この流れを確かめた。止まっている間に届いたリクエストは、すぐつながったものと、約 1 秒、約 2 秒、約 3 秒待ってつながったものに分かれた。 構成 nginx とアプリケーションサーバーを同じ Docker ネットワークのコンテナで動かし、nginx に毎秒 200 件のリクエストを 15 秒送った。送り始めて 5 秒後に、アプリケーションサーバーのプロセスに外から SIGSTOP を送って止め、3 秒後に SIGCONT で再開させた。full GC でプロセス全体が止まる状態を模している。 nginx は 1.30.6 で、upstream ブロックにアプリケーションサーバーを 1 台置いた。proxy_connect_timeout(nginx がアプリケーションサーバーへの接続を張り終えるのを待つ上限)は既定の 60 秒のまま アプリケーションサーバーは受けたリクエストにすぐ 200 を返す HTTP サーバーで、backlog 100 で listen する 接続にかかった時間 止めてから再開させるまでの 3 秒に nginx に届いたリクエストは 600 件で、すべて 200 だった。$upstream_connect_time ごとの件数は次のとおりだ。 $upstream_connect_time 件数 0 秒(すぐつながった) 102 件 約 1 秒 204 件 約 2 秒 205 件 約 3 秒 89 件 冒頭の3行に限らず、600 件とも、アプリケーションサーバーのログの処理時間は 1 ミリ秒未満だった。 表のどの値に入るかは、届いた時刻で決まる。止めてから 0.5 秒ほどでキューが満杯になり、それより前に届いた接続はキューに入って、すぐつながった。それより後に届いた接続は SYN を捨てられ、nginx 側のカーネルが 1 秒ごとに送り直して、アプリケーションサーバーが動き出したあとの次の再送でつながった。早く届いた接続ほど、送り直した回数が多く、待ちが長い。 自分のログで見分ける accept キューが溢れたかどうかは、nginx のアクセスログとアプリケーションサーバーのログを突き合わせて見分ける。アクセスログで SYN が捨てられて再送でつながったと分かり、アプリケーションサーバーのログで、アプリケーションサーバーが止まっていたと分かる。 アクセスログ アクセスログでは、アラートが鳴った時間帯の 200 の行の $upstream_connect_time を見る。値が約 1 秒、約 2 秒、約 3 秒に固まっていれば、SYN が捨てられ、再送でつながっている。 $upstream_connect_time は既定の combined 形式に入らないので、log_format に足す5。検証では次の形式を使った。 log_format lab '$msec $request_id $status uct=$upstream_connect_time uht=$upstream_header_time urt=$upstream_response_time rt=$request_time'; アプリケーションサーバーのログ アプリケーションサーバーのログでは、アクセスログで $upstream_connect_time が 1 秒刻みの値になったリクエストと同じ ID の行と、その時間帯の行の並びを見る。同じ ID のリクエストが速く終わり、その時間帯に行が途切れていれば、アプリケーションサーバーは止まっていた。途切れたあとの行は、動き出した時刻にまとまって並ぶ。 突き合わせるには、nginx がリクエストごとに付ける ID($request_id)をアプリケーションサーバーに渡す。nginx の側は次の1行で渡せる。 proxy_set_header X-Request-Id $request_id; アプリケーションサーバーの側では受け取った X-Request-Id ヘッダをアクセスログに出す設定が要る。 対策 アプリケーションサーバーの backlog の設定を、止まっている間に届く件数(毎秒の件数 × 止まる秒数)より大きくすれば、溢れは起きない6。backlog を 4096 にすると、約 1 秒、約 2 秒、約 3 秒の 200 は出なくなる。 full GC で止まることのある JVM のサーバーの既定の backlog は、次のとおりだ。 Tomcat と Spring Boot:1007 Jetty:508 止まっている間に届いたリクエストは、溢れなくても、アプリケーションサーバーが動き出すまでキューで待たされる。この待ちは $upstream_header_time に出て、止まった時間の分だけ遅い 200 は残る。 環境による違い 接続のタイムアウトを縮めているとき proxy_connect_timeout を止まる時間より短くしていると、再送を待ちきれなかった接続は、nginx が打ち切って 504 を返す。 止まる時間が 3 秒でないとき 止まる時間が違えば、$upstream_connect_time が固まる値も変わるはずだ。この記事では 3 秒止めた場合を確かめている。 6.5 より前のカーネル nginx 側のカーネルが 6.5 より前だと、$upstream_connect_time は約 1 秒と約 3 秒に固まり、約 2 秒は出ない。再送の間隔が 1 秒後、その 2 秒後、その 4 秒後と倍々に伸びるからだ。 Ubuntu 24.04 の標準のカーネル(6.8)は 6.5 以降、Ubuntu 22.04(5.15)、Debian 12(6.1)、RHEL 9(5.14)は 6.5 より前だ。ディストリビューションがこの変更を自分のカーネルに取り込んでいるかは確かめていない。 アプリケーションサーバーの前にプロキシがあるとき nginx とアプリケーションサーバーの間に、先に接続を受けるプロキシ(Docker の公開ポートを受ける userland-proxy、サイドカーのプロキシ)があると、nginx からの SYN にはそのプロキシが返事をする。アプリケーションサーバーのキューが溢れても nginx 側では再送が起きないので、この記事の見分け方は使えないはずだ。この記事では確かめていない。 脚注 普段の GC ではここまで止まらない。JVM の G1 は停止時間の目標が既定で 200ms だ(JDK 25 の G1Arguments::initialize())。秒単位で止まるのは、ヒープが逼迫したときの full GC などで、この記事では確かめていない。 ↩︎ 検証結果はこちら、コードは show-your-work にある。GitHub Actions の ubuntu-24.04(x86_64、カーネル 6.17)で、Docker 28.0.4 を使った。 ↩︎ Linux 6.17 のソースの tcp_conn_request() で、キューが満杯なら SYN を捨てている。満杯かどうかは sk_acceptq_is_full() が決め、キューにある接続の数が backlog より大きい(>)ときに満杯とする。 ↩︎ 1 秒間隔で送り直す回数は net.ipv4.tcp_syn_linear_timeouts(既定 4)で決まる(Linux 6.17 の文書)。 ↩︎ log_format の足し方は nginxのrequest_timeは速いのにユーザーは遅いと言うで扱った。 ↩︎ 4096 より大きくするときは、アプリケーションサーバー側のカーネルの net.core.somaxconn も上げる。カーネルは backlog を somaxconn までに切り詰め(Linux 6.17 の __sys_listen_socket())、その既定は 4096 だ(preinit_net_sysctl()、文書)。 ↩︎ Tomcat 11 の文書の HTTP コネクタの設定と、Spring Boot 4.1.1 のソースの TomcatServerProperties。 ↩︎ Jetty は 0 を渡し、JDK が 50 に置き換える。Jetty 12.1.14 のソースの ServerConnector で既定が 0、JDK 25 のソースの ServerSocketChannelImpl で 1 未満を 50 にしている。 ↩︎

  8. > Unless they need Linux GPU/WIFI/BT drivers to make things work, of course. Then it's fine. The parts of Linux that get integrated into BSDs should not be GPL-licensed, e.g. <github.com/torvalds/linux/blob/c339f4010dea8b0d75…> and its siblings use MIT.

  9. If you're a software engineer and can't spot the bugs in this code, you're cooked torvalds/linux

    13 likes · 344 views
  10. [Ansible] Summary Since your last visit 11 2 25 New Topics Unread Notifications New Users Popular Topics Newsletter October 19 The Bullhorn #236 gundalow This week in Ansible Community Issue #236, 2026-10-16 (Past Issues) Welcome to The Bullhorn, our newsletter for the Ansible Community. If you have any questions or content you’d like to share, you’re welcome to chat with us in the Ansible Social room on Matrix, and mention newsbot to have your news item tagged for review for the next weekly issue! 5 0 Read More Newsletter October 23 The Bullhorn #237 Daniel Brennand dbrennand This week in Ansible Community Issue #237, 2026-10-23 (Past Issues) Welcome to The Bullhorn, our newsletter for the Ansible Community. If you have any questions or content you’d like to share, you’re welcome to chat with us in the Ansible Social room on Matrix, and mention newsbot to have your news item tagged for review for the next weekly issue! 0 0 Read More Get Help October 24 Galaxy API returning HTTP Error 500: Internal Server Error when fetching collection artifacts adpavlov Hello, The Ansible Galaxy API endpoint is currently returning 500 Internal Server Errors when attempting to download collection tarballs. This is breaking our automated installer pipelines. 9 7 Read More Get Help October 21 Cannot get log_plays callback to work ab203972 To preface; I apologize for asking what is probably a very simple question, but no matter what I try, it just doesn’t work. 3 5 Read More Project Discussions October 23 Phoenix Automation Platform (PAP) – Exploring Operational Modernization Built on AWX Erick Mesias Arana mesiaserick Hello Ansible and AWX community, First, I would like to acknowledge the valuable work of the AWX maintainers, contributors, and the broader Ansible community. 0 2 Read More Popular Posts Kernel has recently changed the commit attribution format: coding-assistants: simplify attribution · torvalds/linux@816d999 · GitHub / AI Coding Assistants — The Linux Kernel documentation / The 2026 Maintainers Summit [LWN.net] 🇺🇦 Sviatoslav S. (read: /sʋʲɑtɔˈslɑw/) from the Core Team webknjaz Ansible AI Policy? Read More Hi There was a backend AWS IAM issue, which has been resolved. gundalow Galaxy API returning HTTP Error 500: Internal Server Error when fetching collection artifacts Read More New for you default variables in modular task files Get Help 0 2 Python functions in ansible Guides, FAQs & Howtos 0 0 Namespace: itsyossuf Galaxy Namespace Requests 0 0 Introducing Phoenix Automation Platform (PAP) – Modernizando la automatización sobre AWX Español (Spanish) 0 0 Known issue: galaxy.ansible.com unable to provide collections Get Help 0 0 coding-assistants: simplify attribution · torvalds/linux@816d999 · GitHub: github.com/torvalds/linux/commit/816d9992d9ed

Trending awards, every completed day and week
Gold
91st place finishes
Silver
62nd place finishes
Bronze
133rd place finishes
Awarded repositories
3Owned by torvalds now

Repositories

Ordered by gold, then silver, then bronze.

  1. linuxBest: 1st by stars, 2,302 stars9411
  2. subsurfaceBest: 2nd by stars, 55 stars012
  3. AudioNoiseBest: 2nd by stars, 424 stars010

A repository earns an award for finishing first, second or third in a completed trending day or week, ranked by new stars, new forks or pull request authors. Awards follow a repository through renames and transfers and count toward its current owner. Weeks run Monday to Sunday, UTC.