arm baremetal: SVC explain where the imm16 can be retrieved

Use upper case hex literals on all PRIXnn.

.gitignore /out.docker
This commit is contained in:
Ciro Santilli 六四事件 法轮功
2019-07-16 00:00:01 +00:00
parent b1bfd46efe
commit b38e2b0da9
10 changed files with 140 additions and 75 deletions

2
.gitignore vendored
View File

@@ -1,5 +1,7 @@
# Important directories. # Important directories.
/out /out
# https://github.com/cirosantilli/linux-kernel-module-cheat#docker
/out.docker
/data /data
# Temporary files. # Temporary files.

View File

@@ -10148,7 +10148,7 @@ Behaviour breakdown:
So we take a performance measurement approach instead: So we take a performance measurement approach instead:
.... ....
./gem5-bench-cache --arch aarch64 ./gem5-bench-cache -- --arch aarch64
cat "$(./getvar --arch aarch64 run_dir)/bench-cache.txt" cat "$(./getvar --arch aarch64 run_dir)/bench-cache.txt"
.... ....
@@ -14672,26 +14672,29 @@ Sources:
Sample output for the C one: Sample output for the C one:
.... ....
daif 0x3c0 DAIF 0x3C0
spsel 0x1 SPSEL 0x1
vbar_el1 0x40000800 VBAR_EL1 0x40000800
after_svc 0x4000209c
lkmc_vector_trap_handler lkmc_vector_trap_handler
exc_type 0x11 exc_type 0x11
exc_type is LKMC_VECTOR_SYNC_SPX exc_type is LKMC_VECTOR_SYNC_SPX
ESR 0x56000042 ESR 0x5600ABCD
SP 0x4200bba8 ESR.EC 0x15
ELR 0x40002470 ESR.EC.ISS.imm16 0xABCD
SPSR 0x600003c5 SP 0x4200C510
ELR 0x4000209C
SPSR 0x600003C5
x0 0x0 x0 0x0
x1 0x1 x1 0x1
x2 0x14 x2 0x15
x3 0x14 x3 0x15
x4 0x40008390 x4 0x4000A178
x5 0xfffffff8 x5 0xFFFFFFF6
x6 0x4200ba28 x6 0x4200C390
x7 0x0 x7 0x78
x8 0x0 x8 0x1
x9 0x13 x9 0x14
x10 0x0 x10 0x0
x11 0x0 x11 0x0
x12 0x0 x12 0x0
@@ -14711,11 +14714,36 @@ x25 0x0
x26 0x0 x26 0x0
x27 0x0 x27 0x0
x28 0x0 x28 0x0
x29 0x4200bba8 x29 0x4200C510
x30 0x4000246c x30 0x40002064
.... ....
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: The C code does an:
....
svc 0xABCD
....
and the value 0xABCD appears at the bottom of <<arm-esr-register>>:
....
ESR 0x5600ABCD
ESR.EC 0x15
ESR.EC.ISS.imm16 0xABCD
....
The other important register is the <<arm-elr-register>>, which contains the return address after the exception.
From the output, we can see that it matches the value as obtained by taking the address of a label placed just after the SVC:
....
after_svc 0x4000209c
ELR 0x4000209C
....
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.
With <<qemu-d-tracing>>:
.... ....
./run \ ./run \
@@ -14725,7 +14753,7 @@ Both QEMU and gem5 are able to trace interrupts in addition to instructions, and
; ;
.... ....
contains: the output contains:
.... ....
---------------- ----------------
@@ -14742,7 +14770,7 @@ IN:
0x40000a00: 14000225 b #0x40001294 0x40000a00: 14000225 b #0x40001294
.... ....
and: And with <<gem5-tracing>>:
.... ....
./run \ ./run \
@@ -14753,7 +14781,7 @@ and:
; ;
.... ....
contains: the output contains:
.... ....
4000: system.cpu A0 T0 : @main+8 : svc #0x0 : IntAlu : flags=(IsSerializeAfter|IsNonSpeculative|IsSyscall) 4000: system.cpu A0 T0 : @main+8 : svc #0x0 : IntAlu : flags=(IsSerializeAfter|IsNonSpeculative|IsSyscall)
@@ -14818,6 +14846,20 @@ Bibliography:
* https://stackoverflow.com/questions/44991264/armv8-exception-vectors-and-handling * https://stackoverflow.com/questions/44991264/armv8-exception-vectors-and-handling
* https://stackoverflow.com/questions/44198483/arm-timers-and-interrupts * https://stackoverflow.com/questions/44198483/arm-timers-and-interrupts
===== ARM ESR register
Exception Syndrome Register.
See example at: <<arm-svc-instruction>>
Documentation: <<armarm8-db>> D12.2.36 "ESR_EL1, Exception Syndrome Register (EL1)".
===== ARM ELR register
Exception Link Register.
See example at: <<arm-svc-instruction>>
==== ARM multicore ==== ARM multicore
.... ....

View File

@@ -11,55 +11,68 @@ int myvar = 0;
void lkmc_vector_trap_handler(LkmcVectorExceptionFrame *exception) { void lkmc_vector_trap_handler(LkmcVectorExceptionFrame *exception) {
puts("lkmc_vector_trap_handler"); puts("lkmc_vector_trap_handler");
printf("exc_type 0x%" PRIx64 "\n", exception->exc_type); printf("exc_type 0x%" PRIX64 "\n", exception->exc_type);
if (exception->exc_type == LKMC_VECTOR_SYNC_SPX) { if (exception->exc_type == LKMC_VECTOR_SYNC_SPX) {
puts("exc_type is LKMC_VECTOR_SYNC_SPX"); puts("exc_type is LKMC_VECTOR_SYNC_SPX");
} }
printf("ESR 0x%" PRIx64 "\n", exception->exc_esr); printf("ESR 0x%" PRIX64 "\n", exception->exc_esr);
printf("SP 0x%" PRIx64 "\n", exception->exc_sp); uint64_t esr_ec = (exception->exc_esr >> 26) & 0x3F;
printf("ELR 0x%" PRIx64 "\n", exception->exc_elr); uint64_t iss = exception->exc_esr & 0xFFFFFF;
printf("SPSR 0x%" PRIx64 "\n", exception->exc_spsr); printf("ESR.EC 0x%" PRIX64 "\n", esr_ec);
printf("x0 0x%" PRIx64 "\n", exception->x0); if (
printf("x1 0x%" PRIx64 "\n", exception->x1); esr_ec == LKMC_ESR_EC_SVC_AARCH32 ||
printf("x2 0x%" PRIx64 "\n", exception->x2); esr_ec == LKMC_ESR_EC_SVC_AARCH64
printf("x3 0x%" PRIx64 "\n", exception->x3); ) {
printf("x4 0x%" PRIx64 "\n", exception->x4); printf("ESR.EC.ISS.imm16 0x%" PRIX64 "\n", iss & 0xFFFF);
printf("x5 0x%" PRIx64 "\n", exception->x5); }
printf("x6 0x%" PRIx64 "\n", exception->x6); printf("SP 0x%" PRIX64 "\n", exception->exc_sp);
printf("x7 0x%" PRIx64 "\n", exception->x7); printf("ELR 0x%" PRIX64 "\n", exception->exc_elr);
printf("x8 0x%" PRIx64 "\n", exception->x8); printf("SPSR 0x%" PRIX64 "\n", exception->exc_spsr);
printf("x9 0x%" PRIx64 "\n", exception->x9); printf("x0 0x%" PRIX64 "\n", exception->x0);
printf("x10 0x%" PRIx64 "\n", exception->x10); printf("x1 0x%" PRIX64 "\n", exception->x1);
printf("x11 0x%" PRIx64 "\n", exception->x11); printf("x2 0x%" PRIX64 "\n", exception->x2);
printf("x12 0x%" PRIx64 "\n", exception->x12); printf("x3 0x%" PRIX64 "\n", exception->x3);
printf("x13 0x%" PRIx64 "\n", exception->x13); printf("x4 0x%" PRIX64 "\n", exception->x4);
printf("x14 0x%" PRIx64 "\n", exception->x14); printf("x5 0x%" PRIX64 "\n", exception->x5);
printf("x15 0x%" PRIx64 "\n", exception->x15); printf("x6 0x%" PRIX64 "\n", exception->x6);
printf("x16 0x%" PRIx64 "\n", exception->x16); printf("x7 0x%" PRIX64 "\n", exception->x7);
printf("x17 0x%" PRIx64 "\n", exception->x17); printf("x8 0x%" PRIX64 "\n", exception->x8);
printf("x18 0x%" PRIx64 "\n", exception->x18); printf("x9 0x%" PRIX64 "\n", exception->x9);
printf("x19 0x%" PRIx64 "\n", exception->x19); printf("x10 0x%" PRIX64 "\n", exception->x10);
printf("x20 0x%" PRIx64 "\n", exception->x20); printf("x11 0x%" PRIX64 "\n", exception->x11);
printf("x21 0x%" PRIx64 "\n", exception->x21); printf("x12 0x%" PRIX64 "\n", exception->x12);
printf("x22 0x%" PRIx64 "\n", exception->x22); printf("x13 0x%" PRIX64 "\n", exception->x13);
printf("x23 0x%" PRIx64 "\n", exception->x23); printf("x14 0x%" PRIX64 "\n", exception->x14);
printf("x24 0x%" PRIx64 "\n", exception->x24); printf("x15 0x%" PRIX64 "\n", exception->x15);
printf("x25 0x%" PRIx64 "\n", exception->x25); printf("x16 0x%" PRIX64 "\n", exception->x16);
printf("x26 0x%" PRIx64 "\n", exception->x26); printf("x17 0x%" PRIX64 "\n", exception->x17);
printf("x27 0x%" PRIx64 "\n", exception->x27); printf("x18 0x%" PRIX64 "\n", exception->x18);
printf("x28 0x%" PRIx64 "\n", exception->x28); printf("x19 0x%" PRIX64 "\n", exception->x19);
printf("x29 0x%" PRIx64 "\n", exception->x29); printf("x20 0x%" PRIX64 "\n", exception->x20);
printf("x30 0x%" PRIx64 "\n", exception->x30); 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; myvar = 1;
} }
int main(void) { int main(void) {
/* View initial relevant register values. */ /* View initial relevant register values. */
printf("daif 0x%" PRIx32 "\n", lkmc_sysreg_daif_read()); printf("DAIF 0x%" PRIX32 "\n", lkmc_sysreg_daif_read());
printf("spsel 0x%" PRIx32 "\n", lkmc_sysreg_spsel_read()); printf("SPSEL 0x%" PRIX32 "\n", lkmc_sysreg_spsel_read());
printf("vbar_el1 0x%" PRIx64 "\n", lkmc_sysreg_vbar_el1_read()); printf("VBAR_EL1 0x%" PRIX64 "\n", lkmc_sysreg_vbar_el1_read());
/* https://stackoverflow.com/questions/1777990/is-it-possible-to-store-the-address-of-a-label-in-a-variable-and-use-goto-to-jum */
printf("after_svc %p\n", &&after_svc);
assert(myvar == 0); assert(myvar == 0);
LKMC_SVC(0x42); /* Max 16-bits. */
LKMC_SVC(0xABCD);
after_svc:
assert(myvar == 1); assert(myvar == 1);
return 0; return 0;
} }

View File

@@ -5,7 +5,7 @@
.global main .global main
main: main:
/* Do the svc. */ /* Do the svc. */
svc 0 svc 0xABCD
/* Confirm that svc was called and modified myvar. */ /* Confirm that svc was called and modified myvar. */
ldr x0, myvar ldr x0, myvar

View File

@@ -5,7 +5,7 @@
#include <lkmc/gicv3.h> #include <lkmc/gicv3.h>
void lkmc_vector_trap_handler(LkmcVectorExceptionFrame *exception __attribute__((unused))) { void lkmc_vector_trap_handler(LkmcVectorExceptionFrame *exception __attribute__((unused))) {
printf("CNTVCT_EL0 0x%" PRIx64 "\n", lkmc_sysreg_cntvct_el0_read()); printf("CNTVCT_EL0 0x%" PRIX64 "\n", lkmc_sysreg_cntvct_el0_read());
} }
#define CNTV_CTL_ENABLE (1 << 0) /* Enables the timer */ #define CNTV_CTL_ENABLE (1 << 0) /* Enables the timer */
@@ -30,14 +30,14 @@ void enable_irq(void) {
int main(void) { int main(void) {
/* Initial state. */ /* Initial state. */
printf("CNTV_CTL_EL0 0x%" PRIx32 "\n", lkmc_sysreg_cntv_ctl_el0_read()); printf("CNTV_CTL_EL0 0x%" PRIX32 "\n", lkmc_sysreg_cntv_ctl_el0_read());
printf("CNTFRQ_EL0 0x%" PRIx64 "\n", lkmc_sysreg_cntfrq_el0_read()); printf("CNTFRQ_EL0 0x%" PRIX64 "\n", lkmc_sysreg_cntfrq_el0_read());
printf("CNTV_CVAL_EL0 0x%" PRIx64 "\n", lkmc_sysreg_cntv_cval_el0_read()); printf("CNTV_CVAL_EL0 0x%" PRIX64 "\n", lkmc_sysreg_cntv_cval_el0_read());
/* Get the counter value many times to watch the time pass. */ /* Get the counter value many times to watch the time pass. */
printf("CNTVCT_EL0 0x%" PRIx64 "\n", lkmc_sysreg_cntvct_el0_read()); printf("CNTVCT_EL0 0x%" PRIX64 "\n", lkmc_sysreg_cntvct_el0_read());
printf("CNTVCT_EL0 0x%" PRIx64 "\n", lkmc_sysreg_cntvct_el0_read()); printf("CNTVCT_EL0 0x%" PRIX64 "\n", lkmc_sysreg_cntvct_el0_read());
printf("CNTVCT_EL0 0x%" PRIx64 "\n", lkmc_sysreg_cntvct_el0_read()); printf("CNTVCT_EL0 0x%" PRIX64 "\n", lkmc_sysreg_cntvct_el0_read());
/**/ /**/
gic_v3_initialize(); gic_v3_initialize();
@@ -66,7 +66,7 @@ int main(void) {
/* TODO crashes gem5. */ /* TODO crashes gem5. */
puts("cntfrq_el0 = 1"); puts("cntfrq_el0 = 1");
lkmc_sysreg_cntfrq_el0_write(1); lkmc_sysreg_cntfrq_el0_write(1);
printf("cntfrq_el0 0x%" PRIx64 "\n", lkmc_sysreg_cntfrq_el0_read()); printf("cntfrq_el0 0x%" PRIX64 "\n", lkmc_sysreg_cntfrq_el0_read());
#endif #endif
return 0; return 0;

View File

@@ -28,7 +28,10 @@ lkmc_start:
LKMC_VECTOR_TABLE LKMC_VECTOR_TABLE
/* Default trap handler. */ /* Default handler for exceptions. This is called after some basic
* setup done on the initial handler. Since this is a weak symbol,
* you can redefine it in your own example, and your definition
* will take precedence. */
LKMC_WEAK(lkmc_vector_trap_handler) LKMC_WEAK(lkmc_vector_trap_handler)
ldr x0, =lkmc_vector_trap_handler_error_message ldr x0, =lkmc_vector_trap_handler_error_message
bl puts bl puts

View File

@@ -67,7 +67,7 @@ bench-all() (
if "$generate_checkpoints"; then if "$generate_checkpoints"; then
# Create the checkpoints after the kernel boot. # Create the checkpoints after the kernel boot.
cpt_cmd="-E '/gem5.sh'" cpt_cmd="--eval './gem5.sh'"
# RESTORE_INVESTIGATION # RESTORE_INVESTIGATION
## 5 ## 5
#./eeval "$cmd $cpt_cmd -- $cache_large --cpu-type=HPI" #./eeval "$cmd $cpt_cmd -- $cache_large --cpu-type=HPI"

View File

@@ -92,14 +92,18 @@ main_after_prologue: \
#define LKMC_VECTOR_EXC_FRAME_SIZE (288) /* sizeof(lkmc_vector_exception_frame) */ #define LKMC_VECTOR_EXC_FRAME_SIZE (288) /* sizeof(lkmc_vector_exception_frame) */
#define LKMC_VECTOR_EXC_EXC_TYPE_OFFSET (0) /* offsetof(lkmc_vector_exception_frame, exc_type) */ #define LKMC_VECTOR_EXC_EXC_TYPE_OFFSET (0) /* offsetof(lkmc_vector_exception_frame, exc_type) */
#define LKMC_VECTOR_EXC_EXC_ESR_OFFSE (8) /* offsetof(lkmc_vector_exception_frame, exc_esr) */ #define LKMC_VECTOR_EXC_EXC_ESR_OFFSET (8) /* offsetof(lkmc_vector_exception_frame, exc_esr) */
#define LKMC_VECTOR_EXC_EXC_SP_OFFSET (16) /* offsetof(lkmc_vector_exception_frame, exc_sp) */ #define LKMC_VECTOR_EXC_EXC_SP_OFFSET (16) /* offsetof(lkmc_vector_exception_frame, exc_sp) */
#define LKMC_VECTOR_EXC_EXC_ELR_OFFSET (24) /* offsetof(lkmc_vector_exception_frame, exc_elr) */ #define LKMC_VECTOR_EXC_EXC_ELR_OFFSET (24) /* offsetof(lkmc_vector_exception_frame, exc_elr) */
#define LKMC_VECTOR_EXC_EXC_SPSR_OFFSET (32) /* offsetof(lkmc_vector_exception_frame, exc_spsr) */ #define LKMC_VECTOR_EXC_EXC_SPSR_OFFSET (32) /* offsetof(lkmc_vector_exception_frame, exc_spsr) */
#define LKMC_ESR_EC_SVC_AARCH32 (0x11)
#define LKMC_ESR_EC_SVC_AARCH64 (0x15)
#define LKMC_VECTOR_FUNC_ALIGN .align 2 #define LKMC_VECTOR_FUNC_ALIGN .align 2
#define LKMC_VECTOR_SYMBOL_PREFIX lkmc_vector_ #define LKMC_VECTOR_SYMBOL_PREFIX lkmc_vector_
/* Push several registers on the stack to match LkmcVectorExceptionFrame. */
#define LKMC_VECTOR_BUILD_TRAPFRAME(exc_type) \ #define LKMC_VECTOR_BUILD_TRAPFRAME(exc_type) \
stp x29, x30, [sp, -16]!; \ stp x29, x30, [sp, -16]!; \
stp x27, x28, [sp, -16]!; \ stp x27, x28, [sp, -16]!; \

View File

@@ -310,6 +310,7 @@ path_properties_tuples = (
), ),
'return1.S': {'exit_status': 1}, 'return1.S': {'exit_status': 1},
'semihost_exit.S': {'requires_semihosting': True}, 'semihost_exit.S': {'requires_semihosting': True},
'svc.c': {'cc_pedantic': False},
'timer.c': {'skip_run_unclassified': True}, 'timer.c': {'skip_run_unclassified': True},
}, },
) )

View File

@@ -36,6 +36,6 @@ int main(__attribute__((unused)) int argc, char **argv) {
/* /dev/urandom */ /* /dev/urandom */
fp = fopen("/dev/urandom", "rb"); fp = fopen("/dev/urandom", "rb");
fread(&uint64, sizeof(uint64), 1, fp); fread(&uint64, sizeof(uint64), 1, fp);
printf("/dev/urandom = %" PRIx64 "\n", uint64); printf("/dev/urandom = %" PRIX64 "\n", uint64);
fclose(fp); fclose(fp);
} }