Skip to content

Conversation

@Ivan-Velickovic
Copy link
Contributor

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.

help="QEMU CPU", default="@QEMU_SIM_CPU@")
parser.add_argument('-o', '--cpu-opt', dest='qemu_sim_cpu_opt', type=str,
help="QEMU CPU Options", default="@QEMU_SIM_CPU_OPT@")
parser.add_argument('--smp', dest='qemu_sim_smp', type=str,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the other main arguments have a single letter variant, -s is already taken though so I didn't know what to put here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe -j, like make does?

@Ivan-Velickovic Ivan-Velickovic force-pushed the hvc_support branch 2 times, most recently from 8a53cb9 to cea7513 Compare October 23, 2025 13:07
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I should investigate into HVC on 32-bit ARM.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems to be the same as for 64-bit Arm.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I initially tried that but it failed for 32-bit ARM on QEMU. Will have to debug.

set(sim_cpu_opt "")
set(sim_machine "")
set(qemu_sim_extra_args "")
set(sim_smp "${KernelMaxNumNodes}")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will apply to all simulation targets, but I have only tested ARM.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the Qemu argument is the same, it should work. If not, we're not worse off than before.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is the same across all architectures so yes it should be fine.

@Indanz
Copy link
Contributor

Indanz commented Oct 23, 2025

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?

@midnightveil
Copy link
Contributor

midnightveil commented Oct 23, 2025

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...

@Ivan-Velickovic
Copy link
Contributor Author

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.

@Ivan-Velickovic
Copy link
Contributor Author

Perhaps this clears things up:
https://github.com/qemu/qemu/blob/88b1716a407459c8189473e4667653cb8e4c3df7/hw/arm/virt.c#L2265-L2281

@Ivan-Velickovic Ivan-Velickovic marked this pull request as ready for review November 4, 2025 08:55
@Ivan-Velickovic
Copy link
Contributor Author

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:

  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.
  2. 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?

The motivation for this change is that currently if the elfloader
is trying to boot multiple CPUs for an SMP configuration of seL4,
it will fail unless the PSCI method is SVC. The only other possible
PSCI method that is possible is HVC, which can occur when the system
is being virtualised by something like QEMU and is executing at EL1.

For QEMU, unless it is running with virtualisation explicitly enabled
(`virtualization=on`), it will default to accepting only the HVC PSCI
method. More details are available in comments in the QEMU source [1].

My understanding is the HVC ABI is the exact same as the SMC
one, it's just a difference with exception levels.

[1]: https://github.com/qemu/qemu/blob/88b1716a407459c8189473e4667653cb8e4c3df7/hw/arm/virt.c#L2265-L2281.

Signed-off-by: Ivan Velickovic <[email protected]>
Copy link
Contributor

@Indanz Indanz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer working arm32 support, but otherwise looks fine.

help="QEMU CPU", default="@QEMU_SIM_CPU@")
parser.add_argument('-o', '--cpu-opt', dest='qemu_sim_cpu_opt', type=str,
help="QEMU CPU Options", default="@QEMU_SIM_CPU_OPT@")
parser.add_argument('--smp', dest='qemu_sim_smp', type=str,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe -j, like make does?

set(sim_cpu_opt "")
set(sim_machine "")
set(qemu_sim_extra_args "")
set(sim_smp "${KernelMaxNumNodes}")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the Qemu argument is the same, it should work. If not, we're not worse off than before.

@Indanz
Copy link
Contributor

Indanz commented Nov 5, 2025

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.

@Ivan-Velickovic
Copy link
Contributor Author

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.

@Indanz
Copy link
Contributor

Indanz commented Nov 6, 2025

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.

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.

Note that this does not work for 32-bit ARM, at least when
tested on QEMU with:

../init-build.sh -DPLATFORM=qemu-arm-virt -DAARCH32=1 -DSMP=1

See [1] for details.

[1]: seL4#239 (comment).

Signed-off-by: Ivan Velickovic <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants