From da40e840751a08d56a69000d937834d126b4660e 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: Tue, 16 Jun 2020 02:00:01 +0000 Subject: [PATCH] learn more formally arm 32 bit CP registers, fix QEMU baremetal run with cli args --- README.adoc | 34 ++++++++++++++++++++++++++++++++++ baremetal/arch/arm/dump_regs.c | 29 +++++++++++++++++++++++++++++ lkmc/aarch64_dump_regs.h | 1 + run | 3 ++- 4 files changed, 66 insertions(+), 1 deletion(-) diff --git a/README.adoc b/README.adoc index aac2287..daafbfc 100644 --- a/README.adoc +++ b/README.adoc @@ -21486,6 +21486,35 @@ Guaranteed undefined! Therefore raise illegal instruction signal. Used by GCC `_ Why GNU GAS 2.29 does not have a mnemonic for it in A64 because it is very recent: shows in <> but not `ca`. +==== ARM system register instructions + +Examples of using them can be found at: <> + +aarch64 only uses exactly 2 instructions: + +* MRS: reads a system register to a regular register +* MSR: writes to the system register + +aarch32 is a bit more messy due to older setups, we have both: + +* MRS and MSR which are much like in aarch64 +* coprocessor accesses: +** MRC: reads a system register, C means coprocessor, which is how system registers were previously known as +** MCR: write to the system register +** MRRC: like MRC, but used for the system registers that are marked as 64-bit, and reads to two general purpose regis +** MCRR: write version of MCRR + +<> G1.19.4 "Background to the System register interface" says that only CP14 and CP15 are specified by the ISA: + +____ +The interface to the System registers was originally defined as part of a generic coprocessor interface, that gave access to 15 coprocessors, CP0 - CP15. Of these, CP8 - CP15 were reserved for use by Arm, while CP0 - CP7 were available for IMPLEMENTATION DEFINED coprocessors. +____ + +and the actual coprocessor registers are specified at: + +* CP14: Table G7-1 "Mapping of (coproc ==0b1110) MCR, MRC, and MRRC instruction arguments to System registers" +* CP15: Table G7-3 "VMSAv8-32 (coproc==0b1111) register summary, in MCR/MRC parameter order." + === ARM SIMD Parent section: xref:simd-assembly[xrefstyle=full] @@ -21909,6 +21938,11 @@ ISA quick references can be found in some places: https://static.docs.arm.com/ddi0487/db/DDI0487D_b_armv8_arm.pdf +[[armarm8-fa]] +===== ARMv8 architecture reference manual db + +https://static.docs.arm.com/ddi0487/fa/DDI0487F_a_armv8_arm.pdf + [[armv8-programmers-guide]] ===== Programmer's Guide for ARMv8-A diff --git a/baremetal/arch/arm/dump_regs.c b/baremetal/arch/arm/dump_regs.c index 40400eb..19d55f1 100644 --- a/baremetal/arch/arm/dump_regs.c +++ b/baremetal/arch/arm/dump_regs.c @@ -10,6 +10,35 @@ int main(void) { /* https://cirosantilli.com/linux-kernel-module-cheat#arm-exception-levels */ printf("SPSR.M 0x%" PRIX32 "\n", spsr & 0xF); + /* CP14 https://cirosantilli.com/linux-kernel-module-cheat#arm-system-register-instructions */ + + uint32_t dbgdidr; + __asm__ ("mrc p14, 0, %0, c0, c0, 0" : "=r" (dbgdidr) : :); + printf("DBGDIDR 0x%" PRIX32 "\n", dbgdidr); + +#if !LKMC_GEM5 + uint32_t dbgdrar_0; + uint32_t dbgdrar_1; + __asm__ ("mrrc p14, 0, %0, %1, c1" : "=r" (dbgdrar_0), "=r" (dbgdrar_1) : :); + printf("DBGDRAR 0x%" PRIX64 "\n", dbgdrar_0 | ((uint64_t)dbgdrar_1 << 32)); +#endif + + /* CP15 https://cirosantilli.com/linux-kernel-module-cheat#arm-system-register-instructions */ + + uint32_t midr; + __asm__ ("mrc p15, 0, %0, c0, c0, 0" : "=r" (midr) : :); + printf("MIDR 0x%" PRIX32 "\n", midr); + printf("MIDR.Architecture 0x%" PRIX32 "\n", (midr >> 16) & 0xF); + + uint32_t ctr; + __asm__ ("mrc p15, 0, %0, c0, c0, 0" : "=r" (ctr) : :); + printf("CTR 0x%" PRIX32 "\n", ctr); + + uint32_t ttbr0_0; + uint32_t ttbr0_1; + __asm__ ("mrrc p15, 0, %0, %1, c2" : "=r" (ttbr0_0), "=r" (ttbr0_1) : :); + printf("TTBR0 0x%" PRIX64 "\n", ttbr0_0 | ((uint64_t)ttbr0_1 << 32)); + #if 0 /* TODO blows up exception in EL, but works with -machine secure=on. */ uint32_t nsacr; diff --git a/lkmc/aarch64_dump_regs.h b/lkmc/aarch64_dump_regs.h index 5afe380..ccf0f86 100644 --- a/lkmc/aarch64_dump_regs.h +++ b/lkmc/aarch64_dump_regs.h @@ -5,6 +5,7 @@ /* https://cirosantilli.com/linux-kernel-module-cheat#dump-regs */ +/* So that a sigle source will work with baremetal and printk from kernel module. */ #ifndef LKMC_DUMP_SYSTEM_REGS_PRINTF #define LKMC_DUMP_SYSTEM_REGS_PRINTF printf #endif diff --git a/run b/run index 518c532..54fe6b6 100755 --- a/run +++ b/run @@ -502,6 +502,8 @@ Extra options to append at the end of the emulator command line. )) argv_addr_cur += len(arg) + 1 baremetal_cli_path = os.path.join(self.env['run_dir'], 'baremetal_cli.raw') + if self.env['emulator'] == 'qemu': + self.make_run_dirs() with open(baremetal_cli_path, 'wb') as f: f.write(struct.pack('<{}'.format(self.python_struct_int_format(self.env['int_size'])), len(cli_args))) f.write(b''.join(argv_addr_data)) @@ -702,7 +704,6 @@ Extra options to append at the end of the emulator command line. cpu = 'max' else: extra_emulator_args.extend(extra_qemu_args) - self.make_run_dirs() if debug_vm: serial_monitor = [] else: