From c53ccb02782e6b5ba94c38c72597101cde86c4ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciro=20Santilli=20=E5=85=AD=E5=9B=9B=E4=BA=8B=E4=BB=B6=20?= =?UTF-8?q?=E6=B3=95=E8=BD=AE=E5=8A=9F?= Date: Sun, 23 Sep 2018 17:30:53 +0100 Subject: [PATCH] baremetal: aarch64 semihosting exit --- README.adoc | 5 ++++ baremetal/arch/aarch64/semihost_exit.S | 20 ++++++++++++++ baremetal/arch/arm/semihost_exit.S | 3 ++ baremetal/lib/common.c | 13 +++++++++ build-all | 4 +-- build-baremetal | 38 ++++++++++++++------------ run | 2 +- 7 files changed, 65 insertions(+), 20 deletions(-) create mode 100644 baremetal/arch/aarch64/semihost_exit.S diff --git a/README.adoc b/README.adoc index 42c7bc22..3b1baf35 100644 --- a/README.adoc +++ b/README.adoc @@ -819,6 +819,11 @@ auto_reset_addr_64 = True That patch breaks `--arch arm`, so don't forget to remove it if you want to go back to it. +When doing bare metal programming, it is likely that you will want to learn assembly language basics. Have a look at these tutorials for the userland part: + +* https://github.com/cirosantilli/x86-assembly-cheat +* https://github.com/cirosantilli/arm-assembly-cheat + For more information on baremetal, see the section: <>. The following subjects are particularly important: * <> diff --git a/baremetal/arch/aarch64/semihost_exit.S b/baremetal/arch/aarch64/semihost_exit.S new file mode 100644 index 00000000..6bdecfb1 --- /dev/null +++ b/baremetal/arch/aarch64/semihost_exit.S @@ -0,0 +1,20 @@ +.global main +main: + /* 0x20026 == ADP_Stopped_ApplicationExit */ + mov x1, #0x26 + movk x1, #2, lsl #16 + str x1, [sp,#0] + + /* Exit status code. Host QEMU process exits with that status. */ + mov x0, #0 + str x0, [sp,#8] + + /* x1 contains the address of parameter block. + * Any memory address could be used. */ + mov x1, sp + + /* SYS_EXIT */ + mov w0, #0x18 + + /* Do the semihosting call on A64. */ + hlt 0xf000 diff --git a/baremetal/arch/arm/semihost_exit.S b/baremetal/arch/arm/semihost_exit.S index 8e485d6f..088cad3e 100644 --- a/baremetal/arch/arm/semihost_exit.S +++ b/baremetal/arch/arm/semihost_exit.S @@ -1,5 +1,8 @@ .global main main: + /* SYS_EXIT */ mov r0, #0x18 + /* ADP_Stopped_ApplicationExit */ ldr r1, =#0x20026 + /* Do the semihosting call on A32. */ svc 0x00123456 diff --git a/baremetal/lib/common.c b/baremetal/lib/common.c index a74780b9..c6334bcc 100644 --- a/baremetal/lib/common.c +++ b/baremetal/lib/common.c @@ -58,8 +58,21 @@ int _write(int file, char *ptr, int len) { return len; } +/* Only 0 is supported for now, arm semihosting cannot handle it. */ void _exit(int status) { #if defined(__arm__) __asm__ __volatile__ ("mov r0, #0x18; ldr r1, =#0x20026; svc 0x00123456"); +#elif defined(__aarch64__) + /* TODO actually use the exit value here, just for fun. */ + __asm__ __volatile__ ( + "mov x1, #0x26\n" \ + "movk x1, #2, lsl #16\n" \ + "str x1, [sp,#0]\n" \ + "mov x0, #0\n" \ + "str x0, [sp,#8]\n" \ + "mov x1, sp\n" \ + "mov w0, #0x18\n" \ + "hlt 0xf000\n" + ); #endif } diff --git a/build-all b/build-all index a7d3de3f..4744330b 100755 --- a/build-all +++ b/build-all @@ -22,7 +22,7 @@ for arch in $archs; do if [ ! "$arch" = x86_64 ]; then ./build-crosstool-ng --arch "$arch" ./build-baremetal --arch "$arch" - ./build-baremetal --arch "$arch" -g - ./build-baremetal --arch "$arch" -g --machine RealViewPBX + ./build-baremetal --arch "$arch" --gem5 + ./build-baremetal --arch "$arch" --gem5 --machine RealViewPBX fi done diff --git a/build-baremetal b/build-baremetal index fb086474..f7b74108 100755 --- a/build-baremetal +++ b/build-baremetal @@ -119,23 +119,27 @@ def main(args, extra_args=None): bootloader_obj=bootloader_obj, common_obj=common_obj, ) - build_dir( - os.path.join('arch', args.arch), - gcc=gcc, - cflags=cflags, - entry_address=entry_address, - bootloader_obj=bootloader_obj, - common_obj=common_obj, - ) - build_dir( - os.path.join('arch', args.arch, 'no_bootloader'), - gcc=gcc, - cflags=cflags, - entry_address=entry_address, - bootloader_obj=bootloader_obj, - common_obj=common_obj, - bootloader=False, - ) + arch_dir = os.path.join('arch', args.arch) + if os.path.isdir(os.path.join(common.baremetal_src_dir, arch_dir)): + build_dir( + arch_dir, + gcc=gcc, + cflags=cflags, + entry_address=entry_address, + bootloader_obj=bootloader_obj, + common_obj=common_obj, + ) + arch_dir = os.path.join('arch', args.arch, 'no_bootloader') + if os.path.isdir(os.path.join(common.baremetal_src_dir, arch_dir)): + build_dir( + arch_dir, + gcc=gcc, + cflags=cflags, + entry_address=entry_address, + bootloader_obj=bootloader_obj, + common_obj=common_obj, + bootloader=False, + ) return 0 if __name__ == '__main__': diff --git a/run b/run index c3d4628a..018bb14b 100755 --- a/run +++ b/run @@ -271,7 +271,7 @@ def main(args, extra_args=None): '-device', 'edu', ]) elif args.arch == 'arm' or args.arch == 'aarch64': - extra_qemu_args.append('-semihosting') + extra_emulator_args.append('-semihosting') if args.kgdb: kernel_cli += ' kgdboc=ttyAMA0,115200' if args.arch == 'arm':