elfloader: add support for PSCI functions via HVC
My understanding is the HVC ABI is the exact same as the SMC one, it's just a difference with exception levels.
Also adds a commit to automatically add the right -smp flags with the generated simulate scripts.
Draft because I did this very quickly and need to review my own changes more.
So far I have tested that SMP/uni-core QEMU works and that I haven't broken PSCI SVC functionality by testing SMP on the Odroid-C4.
Considering you want to turn on a real CPU core, I don't see why you would need to use a HVC call instead of a SMC call for that. HCV is to call to a hypervisor running in EL2, SMC is to call into EL3. So except if for some reason SMC just fails and HVC is redirected to EL3, I don't see how using HVC can work while SMC doesn't. Is this some Qemu quirk or am I missing something?
Yeah, I think this might be a weird QEMU quirk. But given how little was needed to fix it...
However there are a few (but not many) boards with device trees that specify that they want HVC calls for PSCI, e.g. https://elixir.bootlin.com/linux/v6.17.4/source/arch/arm64/boot/dts/qcom/msm8994.dtsi#L178. So it's not unreasonable for the device tree to ask for this...
Is this some Qemu quirk or am I missing something?
I don't know why just doing an smc instead does not work, I tried it but it failed to turn on any other CPUs.
I do not know why QEMU has this restriction, I am yet to look into it.
Perhaps this clears things up: https://github.com/qemu/qemu/blob/88b1716a407459c8189473e4667653cb8e4c3df7/hw/arm/virt.c#L2265-L2281
This is ready for review now. I have added more details in the commit message for the motivation and why this is needed in the first place.
I attempted to get 32-bit ARM working but ran into two problems:
- At least for the PSCI version that QEMU expects, the SMC/HVC function IDs are incorrect for 32-bit. E.g for
SMC_FID_CPU_ONit is0x80000003instead of0x84000003. - The function IDs were easy to fix, which then lead to all the CPUs being booted and the kernel started executing, but never dropped to user space.
This is the log I got:
ELF-loader started on CPU: ARM Ltd. Cortex-A15 r2p1
paddr=[40454000..4076104b]
No DTB passed in from boot loader.
Looking for DTB in CPIO archive...found at 4049886c.
Loaded DTB from 4049886c.
paddr=[4004c000..4004dfff]
ELF-loading image 'kernel' to 40000000
paddr=[40000000..4004bfff]
vaddr=[a0000000..a004bfff]
virt_entry=a0000000
ELF-loading image 'rootserver' to 4004e000
paddr=[4004e000..40433fff]
vaddr=[10000..3f5fff]
virt_entry=1d77c
Boot cpu id = 0x0, index=0
Core 1 is up with logic id 1
Core 2 is up with logic id 2
Core 3 is up with logic id 3
Enabling MMU and paging
Jumping to kernel-image entry point...
Bootstrapping kernel
available phys memory regions: 1
[40000000..80000000)
reserved virt address space regions: 4
[a0000000..a004c000)
[a004c000..a004de8e)
[a004e000..a0434000)
[ff000000..ff100000)
I don't know if I have time to debug the 32-bit ARM case, I can type up more details and post it in an issue.
Is it possible to get this merged without 32-bit support?
I attempted to get 32-bit ARM working but ran into two problems:
1. At least for the PSCI version that QEMU expects, the SMC/HVC function IDs are incorrect for 32-bit. E.g for `SMC_FID_CPU_ON` it is `0x80000003` instead of `0x84000003`.
That doesn't make any sense, is this another Qemu quirk?
Please just add the 32-bit support and ignore the problem for now (so no FID work-arounds either). Maybe add a printf that it seems broken on Qemu, but trying anyway.
That doesn't make any sense, is this another Qemu quirk?
I was looking at this PSCI specification (DEN0022F.b_Power_State_Coordination_Interface). Section 5.1.4 says the function ID for SMC32 is 0x84000003, but the elfloader code has it as 0x80000003.
Please just add the 32-bit support and ignore the problem for now (so no FID work-arounds either). Maybe add a printf that it seems broken on Qemu, but trying anyway.
Sure.
That doesn't make any sense, is this another Qemu quirk?
I was looking at this PSCI specification (DEN0022F.b_Power_State_Coordination_Interface). Section 5.1.4 says the function ID for SMC32 is
0x84000003, but the elfloader code has it as0x80000003.
Oh, that's just wrong. Bit 30 determines whether the calling convention is 32 or 64 bits, but Elfloader is using the 32 bit calling convention on 64-bit, so all codes should be the same.