diff options
author | Aaron Lindsay <alindsay@codeaurora.org> | 2018-04-26 11:04:39 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2018-04-26 11:04:39 +0100 |
commit | b5c53d1b3886387874f8c8582b205aeb3e4c3df6 (patch) | |
tree | b8251ec8be6ee34441c47bd9b274abcdac4fcbf6 /target/arm/cpu.c | |
parent | 08267487c99e8150382420936ab72c1e0ad74ce3 (diff) |
target/arm: Add pre-EL change hooks
Because the design of the PMU requires that the counter values be
converted between their delta and guest-visible forms for mode
filtering, an additional hook which occurs before the EL is changed is
necessary.
Signed-off-by: Aaron Lindsay <alindsay@codeaurora.org>
Message-id: 1523997485-1905-8-git-send-email-alindsay@codeaurora.org
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target/arm/cpu.c')
-rw-r--r-- | target/arm/cpu.c | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 1f689f6817..d175c5e94f 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -55,6 +55,17 @@ static bool arm_cpu_has_work(CPUState *cs) | CPU_INTERRUPT_EXITTB); } +void arm_register_pre_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook, + void *opaque) +{ + ARMELChangeHook *entry = g_new0(ARMELChangeHook, 1); + + entry->hook = hook; + entry->opaque = opaque; + + QLIST_INSERT_HEAD(&cpu->pre_el_change_hooks, entry, node); +} + void arm_register_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook, void *opaque) { @@ -554,6 +565,7 @@ static void arm_cpu_initfn(Object *obj) cpu->cp_regs = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, g_free); + QLIST_INIT(&cpu->pre_el_change_hooks); QLIST_INIT(&cpu->el_change_hooks); #ifndef CONFIG_USER_ONLY @@ -721,6 +733,10 @@ static void arm_cpu_finalizefn(Object *obj) g_hash_table_destroy(cpu->cp_regs); + QLIST_FOREACH_SAFE(hook, &cpu->pre_el_change_hooks, node, next) { + QLIST_REMOVE(hook, node); + g_free(hook); + } QLIST_FOREACH_SAFE(hook, &cpu->el_change_hooks, node, next) { QLIST_REMOVE(hook, node); g_free(hook); |