Hi Quentin,
I dug around a bit and I think I have answers for most.
- RK3588 symbol redefinition in assembly
This only happens for clang and I'm a bit confused as to why. Applying the above patch fixing that issue but inspecting the assembly code reveals something really odd.
**With** that patch, with gcc: 25c8c: d510149f msr dbgprcr_el1, xzr 25c90: d538f2e0 mrs x0, s3_0_c15_c2_7 25c94: b2400000 orr x0, x0, #0x1 25c98: d518f2e0 msr s3_0_c15_c2_7, x0 25c9c: 58000020 ldr x0, 0x25ca0 25ca0: d5033fdf isb 25ca4: d503207f wfi 25ca8: d61f0000 br x0
**with** that patch, with clang: 26d2c: d510149f msr dbgprcr_el1, xzr 26d30: d538f2e0 mrs x0, s3_0_c15_c2_7 26d34: b2400000 orr x0, x0, #0x1 26d38: d518f2e0 msr s3_0_c15_c2_7, x0 26d3c: 58000020 ldr x0, 0x26d40 <--- "my" ldr 26d40: d5033fdf isb 26d44: d503207f wfi 26d48: d61f0000 br x0 <--- "my" br 26d4c: 94000e76 bl 0x2a724 26d50: d510149f msr dbgprcr_el1, xzr 26d54: d538f2e0 mrs x0, s3_0_c15_c2_7 26d58: b2400000 orr x0, x0, #0x1 26d5c: d518f2e0 msr s3_0_c15_c2_7, x0 26d60: 58000020 ldr x0, 0x26d64 <--- "my" ldr 26d64: d5033fdf isb 26d68: d503207f wfi 26d6c: d61f0000 br x0 <--- "my" br
So I think the above patch is just a band-aid on what the actually is but I have no idea what could be going on.
If I use this patch instead, to match the other assembly instructions in this file
========================================================================= diff --git a/plat/rockchip/rk3588/drivers/pmu/pmu.c b/plat/rockchip/rk3588/drivers/pmu/pmu.c index f693dbdf0..a4128b214 100644 --- a/plat/rockchip/rk3588/drivers/pmu/pmu.c +++ b/plat/rockchip/rk3588/drivers/pmu/pmu.c @@ -760,10 +760,10 @@ static inline void cpus_pd_req_enter_wfi(void) "mrs x0, S3_0_C15_C2_7\n" "orr x0, x0, #0x1\n" "msr S3_0_C15_C2_7, x0\n" - "wfi_loop:\n" + "1:\n" "isb\n" "wfi\n" - "b wfi_loop\n"); + "b 1b\n"); }
static void nonboot_cpus_off(void)
It happily compiles, though the binary still seems to contain this loop twice.
Using __attribute__((noinline)) the code is not duplicated, but I assume this is expected as it would now simply be a function.
So, the function only runs once, but it has its address taken elsewhere. For the actual call, it does get inlined, as expected. But the address taking bit, it is kept as a standalone function which happens to be places right after. Disassembling with symbols shows this a bit better. My guess would be that clang either isn't smart enough to deduplicate this, or it's doing it on purpose. Gcc must decide to not inline.
- RK3399 warning array subscript 0 is outside array bounds of 'volatile unsigned int[0]' [-Warray-bounds=]
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" In file included from src/dram.c:12: src/dram.c: In function 'm0_main': include/rk3399_mcu.h:15:34: warning: array subscript 0 is outside array bounds of 'volatile unsigned int[0]' [-Warray-bounds=] 15 | (*(volatile unsigned int *)(c)); __v; }) | ~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/rk3399_mcu.h:16:69: note: in definition of macro 'mmio_write_32' 16 | #define mmio_write_32(c, v) ((*(volatile unsigned int *)(c)) = (v)) | ^ src/dram.c:67:23: note: in expansion of macro 'mmio_read_32' 67 | mmio_read_32(PARAM_ADDR + PARAM_FREQ_SELECT)); | ^~~~~~~~~~~~
This function is used in many places, but only in very specific places is it triggering a warning, when PARAM_ADDR is used, but only when accessed from m0 C files.
PARAM_ADDR is set to 0xc0. From !m0 files, access to PARAM_ADDR seems to be done through the M0_PARAM_ADDR which is M0_BINCODE_BASE + PARAM_ADDR. For m0 files, it's directly accessing PARAM_ADDR. I honestly don't really know why it's complaining for m0 files but not the !m0 ones.
This seems identical to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105523. The top-level makefile has a workaround for this and it sets --param=min-pagesize=0. However, this driver has a very peculiar way of building and it does not inherit most of tf-a's flags. Adding that flag to its own internal makefile fixes the issue, but I feel like it's bound to repeat. Can't it be built by the standard tfa build?
- RK3399 expected string in '.incbin' directive
clang seems happy with that error but the linker triggers another one:
ld.lld: warning: ignoring memory region assignment for non-allocatable section '.incbin_sram' ld.lld: error: section '.pmusram' will not fit in region 'PMUSRAM': overflowed by 3928 bytes
The overflow error seems legitimate, increasing PMUSRAM_RSIZE at the top of the linker script fixes it. There's funky alignment in the rule so maybe that's wasting space? I'm sadly not familiar enough with linkers and don't understand the last warning though, hopefully someone else can figure that one out.
Cheers, Boyan