Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement HVC call to switch execution state to aarch64 in EL2
Unfortunately, the main CPU core is still booting the arm64 Linux kernel in EL1... Looking at the LK code (aboot.c and scm.c) the execution state switch to aarch64 happens using a SMC call to TZ (scm_elexec_call). The switch does not seem to involve the HYP firmware though, so we have no good way to intercept that to jump to the aarch64 kernel directly in EL2. Actually, there should be no need to involve TZ for the aarch32 -> aarch64 execution state switch, since we can just do it from EL2. The only requirement is that LK asks the HYP firmware to do the switch with a HVC call instead of a SMC call. To keep the LK changes simple, I have re-implemented the exact same SMC call as a HVC call. This means LK can reuse all the code and just needs to do "hvc" instead of "smc". Implementing the HVC call is fairly simple, we need to: 1. Add an exception vector table 2. Check for exceptions caused by HVC instructions 3. Compare the command in w0 with the expected one (0x200010f) 4. Do some parameter validation 5. Load all the registers from the passed struct el1_system_param 6. And finally, jump to the new aarch64 kernel directly in EL2! This works for the main CPU, but for some weird reason SMP is broken now and the device reboots during SMP bring-up. :( Further debugging shows that TZ tells our HYP firmware to boot all other CPU cores in aarch32 state instead of aarch64. I guess it records if we ever did the SMC call to switch to aarch64 state... :/ For now I just hack the code to forcibly boot all secondary CPU in aarch64 state. A better solution is needed for this but it works quite well for now. All CPUs finally started in EL2! smp: Bringing up secondary CPUs ... CPU1: Booted secondary processor 0x0000000001 [0x410fd030] CPU2: Booted secondary processor 0x0000000002 [0x410fd030] CPU3: Booted secondary processor 0x0000000003 [0x410fd030] smp: Brought up 1 node, 4 CPUs SMP: Total of 4 processors activated. CPU: All CPU(s) started at EL2 ... kvm [1]: IPA Size Limit: 40 bits kvm [1]: Hyp mode initialized successfully Even KVM seems to be mostly working. Great! Mission accomplished :)
- Loading branch information