From 7c2a9c0e9ce3a91e10e94e35223f2359b14c8551 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: Wed, 20 Feb 2019 00:00:01 +0000 Subject: [PATCH] svc: print values, trace interrupt --- README.adoc | 96 ++++++++++++++++++++++++++++++-- baremetal/arch/aarch64/svc.c | 43 +++++++++++++- baremetal/arch/aarch64/svc_asm.S | 2 + lkmc.h | 2 +- 4 files changed, 137 insertions(+), 6 deletions(-) diff --git a/README.adoc b/README.adoc index a4084dc..daf927e 100644 --- a/README.adoc +++ b/README.adoc @@ -11302,9 +11302,11 @@ output: 3 .... -==== ARM exception handling +==== svc -Setup a handler for `svc`, do an `svc`, and observe that the handler got called and returned from C and assembly: +This is the most basic example of exception handling we have. + +We a handler for `svc`, do an `svc`, and observe that the handler got called and returned from C and assembly: .... ./run --arch aarch64 --baremetal arch/aarch64/svc @@ -11316,14 +11318,100 @@ Sources: * link:baremetal/arch/aarch64/svc_asm.S[] * link:baremetal/arch/aarch64/svc.c[] -Output for the C one: +Sample output for the C one: .... daif 0x3c0 spsel 0x1 -vbar_el1 0x0 +vbar_el1 0x40000800 +lkmc_vector_trap_handler +exc_type 0x11 +exc_type is LKMC_VECTOR_SYNC_SPX +ESR 0x56000000 +SP 0x4200bba8 +ELR 0x40002470 +SPSR 0x600003c5 +x0 0x0 +x1 0x1 +x2 0x14 +x3 0x14 +x4 0x40008390 +x5 0xfffffff8 +x6 0x4200ba28 +x7 0x0 +x8 0x0 +x9 0x13 +x10 0x0 +x11 0x0 +x12 0x0 +x13 0x0 +x14 0x0 +x15 0x0 +x16 0x0 +x17 0x0 +x18 0x0 +x19 0x0 +x20 0x0 +x21 0x0 +x22 0x0 +x23 0x0 +x24 0x0 +x25 0x0 +x26 0x0 +x27 0x0 +x28 0x0 +x29 0x4200bba8 +x30 0x4000246c .... +Both QEMU and gem5 are able to trace interrupts in addition to instructions, and it is instructive to enable both and have a look at the traces: + +.... +./run \ + --arch aarch64 \ + --baremetal arch/aarch64/svc_asm + -- -d in_asm,int \ +; +.... + +contains: + +.... +---------------- +IN: +0x40002060: d4000001 svc #0 + +Taking exception 2 [SVC] +...from EL1 to EL1 +...with ESR 0x15/0x56000000 +...with ELR 0x40002064 +...to EL1 PC 0x40000a00 PSTATE 0x3c5 +---------------- +IN: +0x40000a00: 14000225 b #0x40001294 +.... + +and: + +.... +./run \ + --arch aarch64 \ + --baremetal arch/aarch64/svc_asm \ + --trace ExecAll,Faults \ + --trace-stdout \ +; +.... + +contains: + +.... + 4000: system.cpu A0 T0 : @main+8 : svc #0x0 : IntAlu : flags=(IsSerializeAfter|IsNonSpeculative|IsSyscall) + 4000: Supervisor Call: Invoking Fault (AArch64 target EL):Supervisor Call cpsr:0x3c5 PC:0x80000808 elr:0x8000080c newVec: 0x80001200 + 4500: system.cpu A0 T0 : @vector_table+512 : b <_curr_el_spx_sync> : IntAlu : flags=(IsControl|IsDirectControl|IsUncondControl) +.... + +So we see in both cases that the `svc` is done, then an exception happens, and then we just continue running from the exception handler address. + The vector table format is described on <> Table D1-7 "Vector offsets from vector table base address". A good representation of the format of the vector table can also be found at <> Table 10-2 "Vector table offsets from vector table base address". diff --git a/baremetal/arch/aarch64/svc.c b/baremetal/arch/aarch64/svc.c index 11b15d7..a339a28 100644 --- a/baremetal/arch/aarch64/svc.c +++ b/baremetal/arch/aarch64/svc.c @@ -1,3 +1,5 @@ +/* https://github.com/cirosantilli/linux-kernel-module-cheat#svc */ + #include #include #include @@ -7,7 +9,46 @@ int myvar = 0; void lkmc_vector_trap_handler(LkmcVectorExceptionFrame *exception) { - puts("trap handler"); + puts("lkmc_vector_trap_handler"); + printf("exc_type 0x%" PRIx64 "\n", exception->exc_type); + if (exception->exc_type == LKMC_VECTOR_SYNC_SPX) { + puts("exc_type is LKMC_VECTOR_SYNC_SPX"); + } + printf("ESR 0x%" PRIx64 "\n", exception->exc_esr); + printf("SP 0x%" PRIx64 "\n", exception->exc_sp); + printf("ELR 0x%" PRIx64 "\n", exception->exc_elr); + printf("SPSR 0x%" PRIx64 "\n", exception->exc_spsr); + printf("x0 0x%" PRIx64 "\n", exception->x0); + printf("x1 0x%" PRIx64 "\n", exception->x1); + printf("x2 0x%" PRIx64 "\n", exception->x2); + printf("x3 0x%" PRIx64 "\n", exception->x3); + printf("x4 0x%" PRIx64 "\n", exception->x4); + printf("x5 0x%" PRIx64 "\n", exception->x5); + printf("x6 0x%" PRIx64 "\n", exception->x6); + printf("x7 0x%" PRIx64 "\n", exception->x7); + printf("x8 0x%" PRIx64 "\n", exception->x8); + printf("x9 0x%" PRIx64 "\n", exception->x9); + printf("x10 0x%" PRIx64 "\n", exception->x10); + printf("x11 0x%" PRIx64 "\n", exception->x11); + printf("x12 0x%" PRIx64 "\n", exception->x12); + printf("x13 0x%" PRIx64 "\n", exception->x13); + printf("x14 0x%" PRIx64 "\n", exception->x14); + printf("x15 0x%" PRIx64 "\n", exception->x15); + printf("x16 0x%" PRIx64 "\n", exception->x16); + printf("x17 0x%" PRIx64 "\n", exception->x17); + printf("x18 0x%" PRIx64 "\n", exception->x18); + printf("x19 0x%" PRIx64 "\n", exception->x19); + printf("x20 0x%" PRIx64 "\n", exception->x20); + printf("x21 0x%" PRIx64 "\n", exception->x21); + printf("x22 0x%" PRIx64 "\n", exception->x22); + printf("x23 0x%" PRIx64 "\n", exception->x23); + printf("x24 0x%" PRIx64 "\n", exception->x24); + printf("x25 0x%" PRIx64 "\n", exception->x25); + printf("x26 0x%" PRIx64 "\n", exception->x26); + printf("x27 0x%" PRIx64 "\n", exception->x27); + printf("x28 0x%" PRIx64 "\n", exception->x28); + printf("x29 0x%" PRIx64 "\n", exception->x29); + printf("x30 0x%" PRIx64 "\n", exception->x30); myvar = 1; } diff --git a/baremetal/arch/aarch64/svc_asm.S b/baremetal/arch/aarch64/svc_asm.S index e92ad25..95f1df4 100644 --- a/baremetal/arch/aarch64/svc_asm.S +++ b/baremetal/arch/aarch64/svc_asm.S @@ -1,3 +1,5 @@ +/* https://github.com/cirosantilli/linux-kernel-module-cheat#svc */ + #include .global main diff --git a/lkmc.h b/lkmc.h index db515a3..e0ceb83 100644 --- a/lkmc.h +++ b/lkmc.h @@ -80,7 +80,7 @@ void lkmc_assert_fail(); stp x21, x0, [sp, -16]!; \ mrs x21, elr_el1; \ stp xzr, x21, [sp, -16]!; \ - mov x21, (exc_type); \ + mov x21, exc_type; \ mrs x22, esr_el1; \ stp x21, x22, [sp, -16]!