I add a call to gicv3_cpuif_enable ( CPU_0 ) to gic_init() in gic_compat.c and give it a try.
We see this.
Synch exception: 15 6 ESR = 02000000 ESR.EC = 00000000 ELR = 02001EE4 unknown: 00000000 Panic (Synch abort)Tracking down the address in the ELR register, we find:
0000000002001ee0Aha! This certainly merits a Synch exception. We are running at EL2 and we are trying to access the ICC_SRE_EL3 register. The routine right above this is write_icc_sre_el2() which would be the proper routine to call. The code has been built, expecting to run at EL3 (as makes sense for ATF itself).: 2001ee0: d10043ff sub sp, sp, #0x10 2001ee4: d53ecca0 mrs x0, icc_sre_el3 2001ee8: f90007e0 str x0, [sp, #8] 2001eec: f94007e0 ldr x0, [sp, #8] 2001ef0: 910043ff add sp, sp, #0x10 2001ef4: d65f03c0 ret
This is sort of encouraging. Has an interrupt actually happened?
No.
This call is in gicv3_cpuif_enable(). Interestingly, this routine has this near the top:
assert(IS_IN_EL3());Apparently the assert system is not initialized, and could be helping us.
gicv3_main.c:void __init gicv3_driver_init(const gicv3_driver_data_t *plat_driver_data) gicv3_main.c:void __init gicv3_distif_init(void)Currently, when I perform initialization, I call:
gicv3_driver_init ( &rockchip_gic_data );
gicv3_cpuif_enable ( CPU_0 );
I search for the second call, and find this in plat/rockchip/common/rockchip_gicv3.c
void plat_rockchip_gic_init(void)
{
gicv3_distif_init();
gicv3_rdistif_init(plat_my_core_pos());
gicv3_cpuif_enable(plat_my_core_pos());
}
This is routine is called in plat/rockchip/common/bl31_plat_setup.c as follows:o
void bl31_platform_setup(void)
{
generic_delay_timer_init();
plat_rockchip_soc_init();
/* Initialize the gic cpu and distributor interfaces */
plat_rockchip_gic_driver_init();
plat_rockchip_gic_init();
plat_rockchip_pmu_init();
Also of interest are these calls, not marked by __init, but with "_init" in their names:
gicv3_main.c:void gicv3_rdistif_init(unsigned int proc_num) gicv3_main.c:void gicv3_rdistif_init_restore(unsigned int proc_num, const gicv3_redist_ctx_t * const rdist_ctx) gicv3_main.c:void gicv3_distif_init_restore(const gicv3_dist_ctx_t * const dist_ctx)I feel confident that I can ignore the restore/save calls. The first call has already been discovered above.
cd /u1/linux/linux-git ls -lR >zzfiles.listThis provides a list of all source files that I can search using "vi".
cd drivers/irqchip ls -l *gic* -rw-r--r-- 1 tom tom 44619 Dec 23 2022 irq-gic.c -rw-r--r-- 1 tom tom 3698 Dec 23 2022 irq-gic-common.c -rw-r--r-- 1 tom tom 885 Dec 23 2022 irq-gic-common.h -rw-r--r-- 1 tom tom 3554 Dec 23 2022 irq-gic-pm.c -rw-r--r-- 1 tom tom 2251 Dec 23 2022 irq-gic-realview.c -rw-r--r-- 1 tom tom 14682 Dec 23 2022 irq-gic-v2m.c -rw-r--r-- 1 tom tom 62875 Dec 23 2022 irq-gic-v3.c -rw-r--r-- 1 tom tom 141099 Dec 23 2022 irq-gic-v3-its.c -rw-rw-r-- 1 tom tom 4283 Aug 4 2020 irq-gic-v3-its-fsl-mc-msi.c -rw-r--r-- 1 tom tom 5051 Dec 23 2022 irq-gic-v3-its-pci-msi.c -rw-rw-r-- 1 tom tom 3868 Aug 4 2020 irq-gic-v3-its-platform-msi.c -rw-r--r-- 1 tom tom 8178 Dec 23 2022 irq-gic-v3-mbi.c -rw-r--r-- 1 tom tom 9671 Dec 23 2022 irq-gic-v4.cSo linux has gathered up all the drivers for interrupt controllers in the directory "drivers/irqchip" and we find various gic drivers there.
I search for EL3 and EL1 in the linux drivers. I find EL3 only in comments, but many register references are specific to EL1. EL2 is hardly mentioned, only in one comment and in a panic message.
The only linux C source file that has dealings with EL1/EL3 is irq-gic-v3.c The linux code for the gic driver actually looks quite clean and reasonable to understand.
#define NDEBUG #includeThe symbols "NDEBUG" is nowhere to be found in the code we are running, so the thing to do is to look at "assert.h". We see here that ATF has its own scheme involving debug.h and a group of LOG_LEVEL macros. A function __assert() will be called on an assertion failure.
In the ATF code, support for this is in lib/libc/assert.c -- this file is only 35 lines and contains:
void __dead2 __assert(const char *file, unsigned int line)
{
printf("ASSERT: %s:%u\n", file, line);
backtrace("assert");
console_flush();
plat_panic_handler();
There is also cassert.h that acts at compile time. It involves the CASSERT() macro and is not of interest at just this time.
What about this __dead2 thing? It is defined in cdefs.h along with a bunch of other attributes, as follows:
#define __dead2 __attribute__((__noreturn__))As an even further side note, the __init "thing" is more complex and looks like this (if "RECLAIM_INIT_CODE" is defined):
#define __init __section(".text.init." __FILE__ "." __XSTRING(__LINE__)) __noinline
The "noreturn" attribute tells gcc that a function will never return.
This will suppress some pointless warnings and allows certain optimizations.
The ATF code marks many functions with "__dead2", but there is no __dead or __dead1, so who knows why "dead2" is used.
FLAGS += -DLOG_LEVEL=30Now the link shows call to tf_log(), but nothing to __assert() yet. The definition for tf_log() is in common/tf_log.c
A look at assert.h shows that I need to define ENABLE_ASSERTIONS. I just do this in assert.h (the Makefile might be a better place)
And now I add __assert() code to gic_compat.c.
gic_init() called ASSERT: gicv3_main.c: Line: 116 Panic (assert) spinningLooking at this line shows us:
assert(IS_IN_EL3());This is in gicv3_driver_init() and is what we were eager to see all along.
Tom's electronics pages / tom@mmto.org