コグノスケ


link 未来から過去へ表示(*)  link 過去から未来へ表示

link もっと前
2019年4月29日 >>> 2019年4月16日
link もっと後

2019年4月29日

クロスビルド用ツールチェーン - その2

目次: GCC

引き続き、超基本的なbinutils + GCC + glibcの組み合わせのクロスビルド環境を作っています。やや苦戦したものの、ARM, AArch64, RISC-V 64でビルドが通りました。良かった良かった。

残念ながらRISC-V 32はglibcが対応しておらず、libcなしのベアメタル向けコンパイラしか作れませんでした。glibc does not yet support 32-bit systemsと怒られます。glibcの代わりにnewlibなどを使えば、libcありのLinux向けコンパイラが作れるかもしれませんが、試していないのでわかりません。

環境

昔作ったクロスコンパイラをビルドするMakefile(GitHubへのリンク)を改造して、作りました。

前回(その1)検討した通り、本格的に運用するなら独自のビルドツールよりcrosstool-NGかbuildrootに切り替えた方が良いと思います。

ビルド方法

詳細はGitHubを見た方が良いですが、configureに指定しているオプションだけ、ざっと列挙しておきます。

変数の定義(イメージ)

CROSS_ARCH = riscv64-unknown-linux-gnu
TOP_DIR    = `pwd`
CROSS_ROOT = $TOP_DIR/buildroot

PREFIX  ?= $(CROSS_ROOT)
SYSROOT ?= $(CROSS_ROOT)/$(CROSS_ARCH)/sysroot

まずbinutilsは、

binutilsのconfigure

./configure \
  --target=$(CROSS_ARCH) \
  --prefix=$(CROSS_ROOT) \
  --disable-nls \
  --disable-static \
  --disable-werror \
  --with-lib-path=$(CROSS_ROOT)/lib \
  --with-sysroot=$(CROSS_ROOT)

次にgccは、

gcc 1回目 のconfigure

./configure \
  --target=$(CROSS_ARCH) \
  --prefix=$(PREFIX) \
  --enable-languages=c \
  --disable-libatomic \
  --disable-libitm \
  --disable-libgomp \
  --disable-libmudflap \
  --disable-libquadmath \
  --disable-libsanitizer \
  --disable-libssp \
  --disable-libstdcxx-pch \
  --enable-long-long \
  --enable-lto \
  --disable-multiarch \
  --disable-multilib \
  --disable-nls \
  --disable-plugin \
  --disable-shared \
  --disable-threads \
  --disable-__cxa_atexit \
  --without-headers \
  --with-local-prefix=$(SYSROOT) \
  --with-sysroot=$(SYSROOT) \
  --with-newlib

難関のglibcはこんな感じ、

glibcのconfigure

./configure \
  --host=$(CROSS_ARCH) \
  --prefix=$(SYSROOT)/usr \
  --disable-profile \
  --disable-multilib \
  --enable-add-ons \
  --enable-kernel=3.0.0 \
  --disable-multi-arch \
  --enable-obsolete-rpc \
  --with-binutils=$(PREFIX)/bin \
  --with-headers=$(SYSROOT)/usr/include \
  --with-sysroot=$(SYSROOT)

最後にglibcを動的リンク可能なgccは、

gcc 2回目のconfigure

./configure \
  --target=$(CROSS_ARCH) \
  --prefix=$(PREFIX) \
  --enable-languages=c,c++,fortran \
  --enable-libatomic \
  --disable-libitm \
  --enable-libgomp \
  --enable-libmudflap \
  --enable-libquadmath \
  --disable-libsanitizer \
  --enable-libssp \
  --enable-libstdcxx-pch \
  --enable-long-long \
  --enable-lto \
  --disable-multiarch \
  --disable-multilib \
  --enable-nls \
  --enable-plugin \
  --enable-shared \
  --enable-threads=posix \
  --enable-__cxa_atexit \
  --with-local-prefix=$(SYSROOT)/usr \
  --with-build-sysroot=$(SYSROOT) \
  --with-sysroot=$(SYSROOT) \
  --with-native-system-header-dir=/usr/include

この設定が正しいかどうか確証は持てませんが、printfを呼び出すCソースコードをエラーなくビルド可能なコンパイラが作成できるので、良しとします。

引っかかったポイント

色々引っかかったのですが、覚えている限りのエラーと自分が取った対策を列挙しておきます。

どのバージョンのライブラリを組み合わせれば良いかわからない
私はDebianなどの既存Linuxディストリビューションが採用しているバージョンを参考にしました。ホスト側のコンパイラのバージョンも影響するため、昔ビルドが通っていた組み合わせでもビルドが通らないことはあります。
AArch64に変えるとglibcビルドエラー
エラーの内容はredefinition of 'struct user_regs_structでした。何それ……??と思いきや、sysrootにインストールしたLinuxカーネルヘッダがRISC-V向けになっていた凡ミスでした。
glibcビルドエラー
エラーの内容はenable-multi-arch support require gcc, assembler and linker indirect-function supportでした。これは解決方法がわからんので、GCCのconfigureに --disable-multi-archを指定し、回避しています。
gccビルドエラー
エラーの内容はPthreads are required to build libgompでした。これはややこしいので、別建てで書きます。

gccビルドエラー(詳細)

エラーメッセージだけ読むとさっぱりですが、config.logに記録されたテストプログラムとテスト結果によれば、pthread.hが見当たらないと言っているようです。

  • GCCのconfigureに --enable-libgompを指定したため、libgompがビルドされている
  • libgompはpthread.hが見つからないのでPthreads are required to build libgompと文句を言っていた

もちろんGCCの前にglibcのクロスビルドに成功しているので、pthread.hは存在しているものの、

  • glibcのヘッダをインストールする場所を間違えていた
  • gccの --with-native-system-header-dirに指定したパスが間違っていた

これらの原因によって、pthread.hが見えなくなっていたようです。

感想

ツールチェーン構築って大変です。実際に体験すると、crosstool-NGやbuildrootのありがたさが身に沁みます。

編集者:すずき(2023/09/24 11:43)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2019年4月27日

クロスビルド用ツールチェーン - その1

目次: GCC

先日(2019年3月27日の日記参照)クロスビルド向けLLVMのビルド方法がわかったので、今度はクロスビルド向けGCCのツールチェーン(超基本的なbinutils + GCC + glibcの組み合わせ)を作ろうとしていますが、さっぱりうまくいかないです。

そもそもどのバージョンの組み合わせならビルドが通るのか全くわかりません……。対象となるクロス環境(ARM向けなのか、RISC-V向けなのか)と、ホスト側のコンパイラバージョンが影響するようで、昔ビルドが通っていた組み合わせを引っ張り出してきても、今の環境だとビルドが通らないなんてことがおきます。

やりたいこと

ビルドできる組み合わせは頑張れば見つけられるとは思いますが、本来やりたいことはクロスビルド用のコンパイラのソースコードリポジトリをダウンロードし、自分でソースコードに何か変更を入れ、変更した内容も含めてビルドすることです(ダウンロードは最悪手動でも良いですけど)。

世の中にはクロスビルド用のツールチェーンを作成できるツールはいくつかありますが、いずれもtarballからのビルドを想定していて、改変を入れて再ビルドする方法が良くわかりません。

ツールが想定しているリリース用のビルドは、

  • リリースバージョンのtarballか、ソースコードリポジトリのリリースタグを持ってきてビルド
  • 実機で使える形、インストーラなどにパッケージング

開発用は、リリース用に加え、

  • 最新のソースコードリポジトリを持ってくる
  • ソースコードに素早くアクセス、改変
  • 改変した部分だけ差分ビルド
  • (必要なら)モジュールを足す

が必要ですが、意外とできないです……。

クロスビルド用ツールチェーンを作成できるツール

いくつかツールを調べてみました。

Yocto
ソースコードはアクセスしづらいです。例えばAGL(Yoctoを使っています)は、
agl/build/tmp/work-shared/gcc-8.2.0-r0/gcc-8.2.0/
に置かれます。何回見ても覚えられません

ソースコードの改変はできますが、bitbakeはソースコードの変更を認識しないようです。bitbakeにモジュールを明示的に指定すれば良さそうです。もしくはパッチを作ってレシピに足してbitbakeするのがYocto的には正しいのかな?どちらにせよ面倒です。

新たにモジュールを足す方法は、レシピを足すだけなので簡単だと思いますが、それ以外が辛すぎます。開発用には向いていません。
crosstool-NG
ソースコードは、
crosstool-ng/.build/src/gcc-8.2.0/
にあります。アクセスしやすいです。

ソースコードの改変は反映されますが、差分ビルドはしないようで、./ct-ng buildとすると全てビルドしなおされます。ちょっと微妙です。

新たなモジュールの追加はどうやるのかわかりません。Yoctoなどとは違い、コンパイラなどのツールチェーンをビルドする専用ツールなので、Linuxカーネルやbusyboxはビルドしません。足すものはあまりないんじゃないでしょうか。
buildroot
ソースコードは、
buildroot/output/build/host-gcc-final-7.4.0/
にあります。Yoctoよりわかりやすいです。

ソースコードの改変は認識されていないように見えます。ソースコードを変更してmakeしても何もビルドされません

新たなモジュールの追加方法は知らないですが、比較的簡単なのかな…?

ツールチェーン単体だとcrosstool-NGですし、将来的に追加するものを考えるとbuildrootが良さそうですけど。変更を反映して差分ビルドする方法ないのかな……??

編集者:すずき(2023/09/24 11:43)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2019年4月19日

RISC-V SoC搭載ボード探し

目次: RISC-V

Linuxが動くくらいのRISC-VのSoC搭載ボードを探していたのですが、どうやらまだ市販されてなさそうでした……。

代わり(?)にSiFiveの高性能RISC-V SoCであるHiFive Unleashed(リンク)のマニュアルを眺めていました。

HiFive Unleashedは高性能と紹介されていることが多いですが、現状RISC-VはArduinoくらいの小規模SoCがほとんどで、それらと比較して高性能、と言っているのだと思われます。

特に珍しい機能もないですし、最近のテレビやタブレット向けの巨大なARM系SoCと比べると、どうしてもショボく見えてしまうのは仕方ないでしょう。

ああ、でもErrataの章があるのは珍しいかもしれません。

ROCK-2: High 24 address bits are ignored
Workaround
Do not access out-of-bound addresses in software.
I2C-1: I2C interrupt can not be cleared
Workaround
Poll the I2C controller state to wait for TIP (transaction in progress) to go low.

などの豪快なバグがある様子が伺えます。特にROCK-2のWorkaroundは全然Workaroundになっておらずのが面白いです。アクセス違反をするな、と言ってアクセス違反がなくなるならOSの苦労はないでしょ。かなり悲惨なバグです。

ボードには修正したSoCを載せるのか、バグったSoCを強引に搭載するのか、どちらなんでしょうね……。

メモ: 技術系の話はFacebookから転記しておくことにした。

編集者:すずき(2021/08/21 02:54)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2019年4月18日

LinuxのDMAとキャッシュフラッシュ

目次: Linux

昨今のキャッシュを持ったCPUでは、DMAを行う際にCPUのキャッシュのフラッシュ(ダーティデータをメインメモリに書きだす、パージともいう)やインバリデート(キャッシュから消しさる、クリーンともいう)が必須です。

しかしアーキテクチャやCPUの実装によってキャッシュの操作方法は異なるため、LinuxではDMA APIというレイヤでアーキテクチャの差分を隠蔽しています。

LinuxでDMAを行うドライバを書くときの一番単純な作法(=単一の領域にDMAを行う、スキャッターギャザーなどはしない)は、

dma_alloc
バッファ確保
dma_map_single
バッファをCPUのメモリ空間にマップし、CPUから見えるようにする
dma_sync_single_for_cpu
CPUからバッファをアクセスする準備
CPUからバッファにデータを書き込む
dma_sync_single_for_device
デバイスからバッファをアクセスする準備
デバイスからDMAを行いデータを読み込む
dma_unmap_single
バッファのマップをやめる
dma_free
バッファ解放

ざっくりいってこのような感じです。先ほど述べた通り、LinuxのDMA APIにキャッシュのフラッシュやインバリデート関数はありません。ハード依存の操作をなるべく減らし、多数のアーキテクチャに対応しやすくなっているんですね。

実際はいつフラッシュしているのか?

そうはいっても、実際にどこでキャッシュフラッシュしているか、気になると思います。昔、Linux 4.4を調べた情報を引っ張り出してきました。アーキテクチャはAArch64つまり64bitのARMコアです。

AArch64の場合、キャッシュ操作をしているのはdma_sync_single_for_cpu() とdma_sync_single_for_device() です。前者がインバリデート、後者がフラッシュ+インバリデートを行っています。

前者のdma_sync_single_for_cpu() を追いかけてみると、

dma_sync_single_for_cpu()
関数ポインタ経由でops->sync_single_for_cpu() を呼びます。AArch64の場合opsには通常 swiotlbのDMA操作関数が入っています。ですので __swiotlb_sync_single_for_cpu() が呼ばれます
__swiotlb_sync_single_for_cpu()
コヒーレントバッファでない(キャッシュフラッシュがいる)場合 __dma_unmap_area() を呼びます
__dma_unmap_area()
__dma_inv_range() を呼びます
__dma_inv_range()
キャッシュをインバリデートします

こんな感じですね。しつこいですがAArch64の実装を見ただけですので、将来的に変わるかもしれないし、他のアーキテクチャでは仕組みが違います。

直接フラッシュしたがるおじさん

昔のLinuxではキャッシュ操作関数をドライバから使うことができました。その記憶からなのか、たまにフラッシュやインバリデートのようなアーキテクチャ依存の操作を直接呼びたがる人がいます。

今のLinuxではキャッシュ操作関数は当然ありますが、ドライバからは呼べない、つまり呼ぶことを推奨していません。もちろんオープンソースなので改造すれば何でもできますけど、メンテナンス性や再利用性、移植性を下げるだけで、損しかないでしょう。

編集者:すずき(2023/04/29 21:39)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



link もっと前
2019年4月29日 >>> 2019年4月16日
link もっと後

管理用メニュー

link 記事を新規作成

<2019>
<<<04>>>
-123456
78910111213
14151617181920
21222324252627
282930----

最近のコメント5件

  • link 21年3月13日
    すずきさん (03/05 15:13)
    「あー、このプログラムがまずいんですね。ご...」
  • link 21年3月13日
    emkさん (03/05 12:44)
    「キャストでvolatileを外してアクセ...」
  • link 24年1月24日
    すずきさん (02/19 18:37)
    「簡単にできる方法はPowerShellの...」
  • link 24年1月24日
    KKKさん (02/19 02:30)
    「追伸です。\nネットで調べたらマイクロソ...」
  • link 24年1月24日
    KKKさん (02/19 02:25)
    「私もエラーで困ってます\n手動での回復パ...」

最近の記事3件

  • link 24年3月19日
    すずき (03/20 02:52)
    「[モジュラージャックの規格] 古くは電話線で、今だとEthernetで良く見かけるモジュラージャックというコネクタとレセプタク...」
  • link 23年4月10日
    すずき (03/19 11:48)
    「[Linux - まとめリンク] 目次: Linuxカーネル、ドライバ関連。Linuxのstruct pageって何?Linu...」
  • link 24年3月18日
    すずき (03/19 11:47)
    「[画面のブランクを無効にする] 目次: LinuxROCK 3 model CのDebian bullseyeイメージは10分...」
link もっとみる

こんてんつ

open/close wiki
open/close Linux JM
open/close Java API

過去の日記

open/close 2002年
open/close 2003年
open/close 2004年
open/close 2005年
open/close 2006年
open/close 2007年
open/close 2008年
open/close 2009年
open/close 2010年
open/close 2011年
open/close 2012年
open/close 2013年
open/close 2014年
open/close 2015年
open/close 2016年
open/close 2017年
open/close 2018年
open/close 2019年
open/close 2020年
open/close 2021年
open/close 2022年
open/close 2023年
open/close 2024年
open/close 過去日記について

その他の情報

open/close アクセス統計
open/close サーバ一覧
open/close サイトの情報

合計:  counter total
本日:  counter today

link About www2.katsuster.net
RDFファイル RSS 1.0

最終更新: 03/20 02:52