Linux
RaspberryPi
arm64
Raspberrypi3
aarch64

RaspberryPi3 Model Bを64bitで動かす

やりたいこと

RaspberryPi3 Model Bを64bitで動かしたくなりました。
せっかく64bit CPU (Cortex-A53)が載っているのに、標準イメージ(32bit)で動かすなんてもったいない!ですよね?
カーネルだけではなく、rootfsも含めて64bitで動作させます。

おおまかな流れ

基本的にgentoo linux wikiのRaspberry_Pi_3_64_bit_Installに沿っています。
さすがgentooだけあって細かく手順を書いてくれてます。

ただし、gentoo linux PCが手元になかったので、Ubuntu16.04 PC上で作業しました。
また、wikiではSDカードに直接書き込んでますが、SDカードがない環境でも作業できるよう、イメージを作成してから流し込むようにしています。

環境

  • PC: Ubuntu 16.04
  • RaspberryPi 3 model B

ツールのインストール

$ sudo apt install gcc-5-aarch64-linux-gnu
$ sudo apt install kpartx

Linux Kernelビルド

$ git clone --depth 1 --branch rpi-4.10.y https://github.com/raspberrypi/linux
$ cd linux
$ ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make bcmrpi3_defconfig
$ ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make -j9
$ cd ..

空のディスクイメージ作成

$ fallocate -l 2GiB GentooAarch64_`date +%Y%m%d`.img

Partitionの作成

$ fdisk GentooAarch64_20171114.img
Welcome to fdisk (util-linux 2.27.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Device does not contain a recognized partition table.
Created a new DOS disklabel with disk identifier 0x1218c51a.

コマンド (m でヘルプ): o
Created a new DOS disklabel with disk identifier 0x8c0219cc.

コマンド (m でヘルプ): n
Partition type
   p   primary (0 primary, 0 extended, 4 free)
      e   extended (container for logical partitions)
      Select (default p):

Using default response p.
パーティション番号 (1-4, default 1):
First sector (2048-4194303, default 2048):
Last sector, +sectors or +size{K,M,G,T,P} (2048-4194303, default 4194303): +128M

Created a new partition 1 of type 'Linux' and of size 128 MiB.

コマンド (m でヘルプ): n
Partition type
   p   primary (1 primary, 0 extended, 3 free)
      e   extended (container for logical partitions)
      Select (default p):

Using default response p.
パーティション番号 (2-4, default 2):
First sector (264192-4194303, default 264192):
Last sector, +sectors or +size{K,M,G,T,P} (264192-4194303, default 4194303):

Created a new partition 2 of type 'Linux' and of size 1.9 GiB.

コマンド (m でヘルプ): t
パーティション番号 (1,2, default 2): 1
Partition type (type L to list all types): c

Changed type of partition 'Linux' to 'W95 FAT32 (LBA)'.

コマンド (m でヘルプ): t
パーティション番号 (1,2, default 2): 2
Partition type (type L to list all types): 82

Changed type of partition 'Linux' to 'Linux swap / Solaris'.

コマンド (m でヘルプ): p
Disk GentooAarch64_20171114.img: 2 GiB, 2147483648 bytes, 4194304 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x8c0219cc

デバイス                    起動  Start 最後から セクタ  Size Id タイプ
GentooAarch64_20171114.img1        2048   264191  262144  128M  c W95 FA
GentooAarch64_20171114.img2      264192  4194303 3930112  1.9G 82 Linux

コマンド (m でヘルプ): w
The partition table has been altered.
Syncing disks.

ファイルシステムの作成

$ sudo kpartx -av GentooAarch64_20171114.img 
add map loop0p1 (253:0): 0 262144 linear 7:0 2048
add map loop0p2 (253:1): 0 3930112 linear 7:0 264192

$ lsblk /dev/loop0
NAME      MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
loop0       7:0    0    2G  0 loop 
├─loop0p2 253:1    0  1.9G  0 part 
└─loop0p1 253:0    0  128M  0 part

$ sudo mkfs -t vfat -F 32 /dev/mapper/loop0p1
mkfs.fat 3.0.28 (2015-05-16)
unable to get drive geometry, using default 255/63

$ sudo mkfs -i 8192 -t ext4 /dev/mapper/loop0p2
mke2fs 1.42.13 (17-May-2015)
Discarding device blocks: done                            
Creating filesystem with 491264 4k blocks and 245760 inodes
Filesystem UUID: 0391b4da-c88d-4cb4-9da8-2a51b7f7f2fa
Superblock backups stored on blocks: 
    32768, 98304, 163840, 229376, 294912

Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (8192 blocks): done
Writing superblocks and filesystem accounting information: done

Root file system

$ mkdir mnt
$ sudo mount /dev/mapper/loop0p2 mnt/
$ curl -L -O http://ftp.jaist.ac.jp/pub/Linux/Gentoo/experimental/arm64/stage3-arm64-arm64-20170223.tar.bz2
$ sudo tar xvf stage3-arm64-arm64-20170223.tar.bz2 -C mnt/
$ sudo rm -rf mnt/tmp/ mnt/boot
$ sudo mkdir mnt/tmp/ mnt/boot

Boot partition

$ sudo mount /dev/mapper/loop0p1 mnt/boot
$ git clone --depth=1 https://github.com/raspberrypi/firmware.git
  # 確認時のSHA1は008700b83121b92
$ sudo cp -r firmware/boot/* mnt/boot/
$ sudo cp linux/arch/arm64/boot/Image mnt/boot/kernel8.img
$ sudo mv mnt/boot/bcm2710-rpi-3-b.dtb mnt/boot/bcm2710-rpi-3-b.dtb_32
$ sudo cp linux/arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dtb mnt/boot
$ cd linux/
$ sudo ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make modules_install INSTALL_MOD_PATH=../mnt
$ cd ..

configuration

rootのパスワード設定(raspberry

$ sudo emacs mnt/etc/shadow
root:$6$xxPVR/Td5iP$/7Asdgq0ux2sgNkklnndcG4g3493kUYfrrdenBXjxBxEsoLneJpDAwOyX/kkpFB4pU5dlhHEyN0SK4eh/WpmO0::0:99999:7:::

ファイルシステムのマウント設定

$ sudo emacs mnt/etc/fstab
/dev/mmcblk0p1          /boot           vfat            noauto,noatime  1 2
/dev/mmcblk0p2          /               ext4            noatime         0 1

Unmount image

$ sudo umount mnt/boot
$ sudo umount mnt
$ sudo kpartx -d GentooAarch64_20171114.img

イメージの書き込み

書き込み先SDカードのデバイスは、差し込み前後のdf -hdmesgで確認できます。
ただし、df -hの出力が/dev/sdc1の場合、最後の1はパーティションを表すので、/dev/sdcを書き込み先とします。

$ sudo umount /dev/sdX1
$ sudo dd bs=4M if=GentooAarch64_20171114.img of=/dev/sdX status=progress conv=fsync
$ sync && sync && sync

64bitであるかどうか確認

上記SDカードでラズパイを起動したら、下記コマンドで64bitで動いているかどうかを確認してみます。
(全く同じ手順であれば、root/raspberryでログインできるはずです)

# Kernel
$ uname -m
aarch64

# rootfs
$ getconf LONG_BIT
64

# rootfs(念押し)
$ readelf -h `which readelf`
  Machine:     AARCH64

成功!

まとめ

せっかくのaarch64なのだから、公式で64bit版サポートして欲しいなと思いつつ、とても勉強になったので結果オーライです。
それにしてもまさか初めてのgentoo linuxがラズパイになるとは思いませんでした汗

参考