ARMv8中,aarch64和aarch32是通过异常进行切换的。而A32和T32是通过bx指令进行切换的。如下图:
以下A64和A32混合编程,是在EL3为aarch64, EL2为aarch32条件下进行编程。在EL3,设置EL2的架构为aarch32,设置好返回地址,通过ERET指令,切换到EL2。
对于A64代码,使用aarch64编译工具链进行编译。
对于A32代码,使用arm编译工具链。
[root@centos7 arm]# wget https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-aarch64-aarch64-none-elf.tar.xz --2022-03-09 07:12:23-- https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-aarch64-aarch64-none-elf.tar.xz Resolving developer.arm.com (developer.arm.com)... 23.76.74.223 Connecting to developer.arm.com (developer.arm.com)|23.76.74.223|:443... connected. HTTP request sent, awaiting response... 302 Moved Temporarily Location: https://armkeil.blob.core.windows.net/developer/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-aarch64-aarch64-none-elf.tar.xz [following] --2022-03-09 07:12:24-- https://armkeil.blob.core.windows.net/developer/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-aarch64-aarch64-none-elf.tar.xz Resolving armkeil.blob.core.windows.net (armkeil.blob.core.windows.net)... 52.239.137.100 Connecting to armkeil.blob.core.windows.net (armkeil.blob.core.windows.net)|52.239.137.100|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 93906188 (90M) [application/octet-stream] Saving to: ‘gcc-arm-10.3-2021.07-aarch64-aarch64-none-elf.tar.xz’ 100%[======================================================================================================================================================================================================================>] 93,906,188 6.08MB/s in 16s 2022-03-09 07:12:41 (5.66 MB/s) - ‘gcc-arm-10.3-2021.07-aarch64-aarch64-none-elf.tar.xz’ saved [93906188/93906188] [root@centos7 arm]# uname -a Linux centos7 4.14.0-115.el7a.0.1.aarch64 #1 SMP Sun Nov 25 20:54:21 UTC 2018 aarch64 aarch64 aarch64 GNU/Linux [root@centos7 arm]#
[root@centos7 arm]# ls gcc-arm-10.3-2021.07-aarch64-aarch64-none-elf 10.3-2021.07-aarch64-aarch64-none-elf-manifest.txt aarch64-none-elf bin include lib libexec share [root@centos7 arm]# ls gcc-arm-10.3-2021.07-aarch64-aarch64-none-elf/bin/ aarch64-none-elf-addr2line aarch64-none-elf-c++filt aarch64-none-elf-gcc aarch64-none-elf-gcc-ranlib aarch64-none-elf-gdb aarch64-none-elf-ld aarch64-none-elf-objcopy aarch64-none-elf-size aarch64-none-elf-ar aarch64-none-elf-cpp aarch64-none-elf-gcc-10.3.1 aarch64-none-elf-gcov aarch64-none-elf-gdb-add-index aarch64-none-elf-ld.bfd aarch64-none-elf-objdump aarch64-none-elf-strings aarch64-none-elf-as aarch64-none-elf-elfedit aarch64-none-elf-gcc-ar aarch64-none-elf-gcov-dump aarch64-none-elf-gfortran aarch64-none-elf-lto-dump aarch64-none-elf-ranlib aarch64-none-elf-strip aarch64-none-elf-c++ aarch64-none-elf-g++ aarch64-none-elf-gcc-nm aarch64-none-elf-gcov-tool aarch64-none-elf-gprof aarch64-none-elf-nm aarch64-none-elf-readelf [root@centos7 arm]# ls gcc-arm-10.3-2021.07-aarch64-aarch64-none-elf/bin/aarch64-none-elf-g aarch64-none-elf-g++ aarch64-none-elf-gcc-10.3.1 aarch64-none-elf-gcc-nm aarch64-none-elf-gcov aarch64-none-elf-gcov-tool aarch64-none-elf-gdb-add-index aarch64-none-elf-gprof aarch64-none-elf-gcc aarch64-none-elf-gcc-ar aarch64-none-elf-gcc-ranlib aarch64-none-elf-gcov-dump aarch64-none-elf-gdb aarch64-none-elf-gfortran [root@centos7 arm]# ls gcc-arm-10.3-2021.07-aarch64-aarch64-none-elf/bin/aarch64-none-elf-gcc aarch64-none-elf-gcc aarch64-none-elf-gcc-10.3.1 aarch64-none-elf-gcc-ar aarch64-none-elf-gcc-nm aarch64-none-elf-gcc-ranlib [root@centos7 arm]# ls gcc-arm-10.3-2021.07-aarch64-aarch64-none-elf/bin/aarch64-none-elf-gcc -version ls: invalid option -- 'e' Try 'ls --help' for more information. [root@centos7 arm]# gcc-arm-10.3-2021.07-aarch64-aarch64-none-elf/bin/aarch64-none-elf-gcc -version aarch64-none-elf-gcc: error: unrecognized command-line option '-version' aarch64-none-elf-gcc: fatal error: no input files compilation terminated. [root@centos7 arm]# gcc-arm-10.3-2021.07-aarch64-aarch64-none-elf/bin/aarch64-none-elf-gcc -h aarch64-none-elf-gcc: error: missing argument to '-h' aarch64-none-elf-gcc: fatal error: no input files compilation terminated. [root@centos7 arm]# gcc-arm-10.3-2021.07-aarch64-aarch64-none-elf/bin/aarch64-none-elf-gcc --help Usage: aarch64-none-elf-gcc [options] file... Options: -pass-exit-codes Exit with highest error code from a phase. --help Display this information. --target-help Display target specific command line options. --help={common|optimizers|params|target|warnings|[^]{joined|separate|undocumented}}[,...]. Display specific types of command line options. (Use '-v --help' to display command line options of sub-processes). --version Display compiler version information. -dumpspecs Display all of the built in spec strings. -dumpversion Display the version of the compiler. -dumpmachine Display the compiler's target processor. -print-search-dirs Display the directories in the compiler's search path. -print-libgcc-file-name Display the name of the compiler's companion library. -print-file-name=<lib> Display the full path to library <lib>. -print-prog-name=<prog> Display the full path to compiler component <prog>. -print-multiarch Display the target's normalized GNU triplet, used as a component in the library path. -print-multi-directory Display the root directory for versions of libgcc. -print-multi-lib Display the mapping between command line options and multiple library search directories. -print-multi-os-directory Display the relative path to OS libraries. -print-sysroot Display the target libraries directory. -print-sysroot-headers-suffix Display the sysroot suffix used to find headers. -Wa,<options> Pass comma-separated <options> on to the assembler. -Wp,<options> Pass comma-separated <options> on to the preprocessor. -Wl,<options> Pass comma-separated <options> on to the linker. -Xassembler <arg> Pass <arg> on to the assembler. -Xpreprocessor <arg> Pass <arg> on to the preprocessor. -Xlinker <arg> Pass <arg> on to the linker. -save-temps Do not delete intermediate files. -save-temps=<arg> Do not delete intermediate files. -no-canonical-prefixes Do not canonicalize paths when building relative prefixes to other gcc components. -pipe Use pipes rather than intermediate files. -time Time the execution of each subprocess. -specs=<file> Override built-in specs with the contents of <file>. -std=<standard> Assume that the input sources are for <standard>. --sysroot=<directory> Use <directory> as the root directory for headers and libraries. -B <directory> Add <directory> to the compiler's search paths. -v Display the programs invoked by the compiler. -### Like -v but options quoted and commands not executed. -E Preprocess only; do not compile, assemble or link. -S Compile only; do not assemble or link. -c Compile and assemble, but do not link. -o <file> Place the output into <file>. -pie Create a dynamically linked position independent executable. -shared Create a shared library. -x <language> Specify the language of the following input files. Permissible languages include: c c++ assembler none 'none' means revert to the default behavior of guessing the language based on the file's extension. Options starting with -g, -f, -m, -O, -W, or --param are automatically passed on to the various sub-processes invoked by aarch64-none-elf-gcc. In order to pass other options on to these processes the -W<letter> options must be used. For bug reporting instructions, please see: <https://bugs.linaro.org/>. [root@centos7 arm]# gcc-arm-10.3-2021.07-aarch64-aarch64-none-elf/bin/aarch64-none-elf-gcc --version aarch64-none-elf-gcc (GNU Toolchain for the A-profile Architecture 10.3-2021.07 (arm-10.29)) 10.3.1 20210621 Copyright (C) 2020 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. [root@centos7 arm]#
[root@centos7 step-08]# make [GCC] commands.o [GCC] kernel.o [GCC] shell.o [GCC] string.o [GCC] uart1.o [GCC] util.o [LD] kernel8.elf /root/arm/gcc-arm-10.3-2021.07-aarch64-aarch64-none-elf/bin/aarch64-none-elf-ld: /lib64/libc.so.6: version `GLIBC_2.27' not found (required by /root/arm/gcc-arm-10.3-2021.07-aarch64-aarch64-none-elf/bin/aarch64-none-elf-ld) make: *** [Makefile:43: kernel8.elf] Error 1 [root@centos7 step-08]#
换个操作系统
root@ubuntu:~# uname -a Linux ubuntu 5.0.0-23-generic #24~18.04.1-Ubuntu SMP Mon Jul 29 16:10:24 UTC 2019 aarch64 aarch64 aarch64 GNU/Linux root@ubuntu:~#
Last login: Wed Mar 9 20:08:15 2022 from 192.168.116.24 root@ubuntu:~# uname -a Linux ubuntu 5.0.0-23-generic #24~18.04.1-Ubuntu SMP Mon Jul 29 16:10:24 UTC 2019 aarch64 aarch64 aarch64 GNU/Linux root@ubuntu:~# ldd --version ldd (Ubuntu GLIBC 2.27-3ubuntu1) 2.27 Copyright (C) 2018 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Written by Roland McGrath and Ulrich Drepper. root@ubuntu:~# whereis libc.so.6 libc.so: /lib/aarch64-linux-gnu/libc.so.6 /usr/lib/aarch64-linux-gnu/libc.so root@ubuntu:~# strings /lib/aarch64-linux-gnu/libc.so.6 | grep GLIBC GLIBC_2.17 GLIBC_2.18 GLIBC_2.22 GLIBC_2.23 GLIBC_2.24 GLIBC_2.25 GLIBC_2.26 GLIBC_2.27 GLIBC_PRIVATE GNU C Library (Ubuntu GLIBC 2.27-3ubuntu1.3) stable release version 2.27. root@ubuntu:~#
root@ubuntu:~/arm/bare-metal-aarch64# ls README.md step-00 step-01 step-02 step-03 step-04 step-05 step-06 step-07 step-08 root@ubuntu:~/arm/bare-metal-aarch64# cd step-08 root@ubuntu:~/arm/bare-metal-aarch64/step-08# ls boot.o boot.S commands.c commands.o include kernel8.ld kernel.c kernel.o Makefile README.md shell.c shell.o string.c string.o uart1.c uart1.o util.c util.o root@ubuntu:~/arm/bare-metal-aarch64/step-08# make [LD] kernel8.elf [OBJCOPY] kernel8.img root@ubuntu:~/arm/bare-metal-aarch64/step-08# cat Makefile # Relative path to the prefix where the compiler was installed. COMPILER_PREFIX = ~/arm/gcc-arm-10.3-2021.07-aarch64-aarch64-none-elf # Prefix to use before all binutils, gcc and gdb commands. BINROOT = ${COMPILER_PREFIX}/bin/aarch64-none-elf- # Variable used to control the printing of commands. # Printing is disabled by default (due to the "@"). # To enable command printing run "make Q= ..." instead of "make ...". Q = @ # Flags passed to GCC. GCC_FLAGS = \ -ffreestanding \ -Wall -Wextra -Werror -pedantic \ -O0 \ -I ./include \ -mgeneral-regs-only # Flags passed to QEMU. QEMU_FLAGS = -M raspi3 -nographic -serial null -serial mon:stdio .PHONY: all all: kernel8.img boot.o: boot.S @echo "[AS] $@" ${Q}${BINROOT}as -c $< -o $@ # All header files. C_HDR = $(wildcard include/*.h) $(wildcard include/bcm2837/*.h) %.o: %.c ${C_HDR} @echo "[GCC] $@" ${Q}${BINROOT}gcc ${GCC_FLAGS} -c $< -o $@ # All C source files, and corresponding object files. C_SRC = $(wildcard *.c) C_OBJ = $(C_SRC:.c=.o) kernel8.elf: kernel8.ld boot.o ${C_OBJ} @echo "[LD] $@" ${Q}${BINROOT}ld -T $< -o $@ $(filter-out $<,$^) kernel8.img: kernel8.elf @echo "[OBJCOPY] $@" ${Q}${BINROOT}objcopy -O binary $< $@ .PHONY: run run: kernel8.img @echo "[QEMU] running with $<" @echo "(Press Ctrl-A X to exit QEMU.)" ${Q}qemu-system-aarch64 ${QEMU_FLAGS} -kernel $< .PHONY: run-gdb run-gdb: kernel8.img @echo "[QEMU] running with $< (waiting for GDB)" @echo "(Press Ctrl-A X to exit QEMU.)" ${Q}qemu-system-aarch64 ${QEMU_FLAGS} -s -S -kernel $< .PHONY: gdb gdb: kernel8.elf @echo "[GDB] running with $<" ${Q}${BINROOT}gdb -ex "target remote :1234" $< .PHONY: clean clean: @rm -f *.o @rm -f kernel8.elf @rm -f kernel8.img root@ubuntu:~/arm/bare-metal-aarch64/step-08# make run [QEMU] running with kernel8.img (Press Ctrl-A X to exit QEMU.) ******************************************** * Hello, World!! * ******************************************** Initial value of x1: 0x0000000000000000. Initial value of x2: 0x0000000000000000. Initial value of x3: 0x0000000000000000. Initial entry point: 0x0000000000080000. Initial exception level: EL2. Current exception level: EL1. Address of the DTB: n/a Entering the interactive mode. > > his Error: unknown command "his". Use command "help" to get a list of commands. > help List of available commands: - "help": list the available commands. - "echo": print each of its arguments. - "hexdump": dump memory starting at ARG1 for ARG2 bytes. - "inc": increment the secret counter via un hypervisor call. - "get": get the value of the secret counter via un hypervisor call. > inc >
root@ubuntu:~/arm/bare-metal-aarch64/step-08# make run [QEMU] running with kernel8.img (Press Ctrl-A X to exit QEMU.) ******************************************** * Hello, World!! * ******************************************** Initial value of x1: 0x0000000000000000. Initial value of x2: 0x0000000000000000. Initial value of x3: 0x0000000000000000. Initial entry point: 0x0000000000080000. Initial exception level: EL2. Current exception level: EL1. Address of the DTB: n/a Entering the interactive mode. > > his Error: unknown command "his". Use command "help" to get a list of commands. > help List of available commands: - "help": list the available commands. - "echo": print each of its arguments. - "hexdump": dump memory starting at ARG1 for ARG2 bytes. - "inc": increment the secret counter via un hypervisor call. - "get": get the value of the secret counter via un hypervisor call. > inc > get The secret counter has value 1 >