Re: [PATCH] arm64: hibernate: pass HVC_SET_VECTORS args to the resume hvc
Will Deacon <[email protected]>
| Newsgroups | org.infradead.lists.linux-arm-kernel,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <aoxl1ri43eEAsxlR@willie-the-truck> |
Hi Vladimir, On Mon, Aug 17, 2026 at 02:06:20PM +0100, Vladimir Murzin wrote: > On 8/11/26 15:37, Will Deacon wrote: > > I think I probably need to spend some time understanding how all this is > > supposed to work. I can't currently tell how we end up with the stub > > vectors installed to start with nor why we can't do all this from C code. I finally got back to this... > Here is my understanding of how things work. Assuming nVHE mode, we > restore the previously saved image X from the currently running kernel Y. > I’ll use the suffixes _X and _Y for addresses belonging to the respective > images. Nice, thanks for the walkthrough! > On the resume path, KVM teardown sets VBAR_EL2 to __hyp_stub_vectors_Y. > > swsusp_arch_resume() then temporarily (re)sets VBAR_EL2 to trans_pgd_stub_vectors > while transitioning to image X: > > | if (el2_reset_needed()) > | __hyp_set_vectors(el2_vectors); > > > Currently, swsusp_arch_suspend_exit() attempts to restore VBAR_EL2 to > __hyp_stub_vectors_X: > > > | cbz x24, 3f /* Do we need to re-initialise EL2? */ > | hvc #0 > > where x24 is resume_hdr.__hyp_stub_vectors (in other words snapshot of > __hyp_stub_vectors from image X) > > However, that request is ignored, so VBAR_EL2 remains pointing to > trans_pgd_stub_vectors > > We re-enter the kernel X. > > During KVM initialisation, we call __hyp_reset_vectors(). This is > handled by trans_pgd_stub_vectors, but ignored since HVC_RESET_VECTORS > is not recognised. We then call __hyp_set_vectors(), which is also > handled by trans_pgd_stub_vectors, but this time VBAR_EL2 get set to > __kvm_hyp_init_X. > > From that point on, __kvm_hyp_init_X handles subsequent HVC calls, > including the later call that redirects VBAR_EL2 to > __kvm_hyp_host_vector_X during KVM setup. > > The memory containing trans_pgd_stub_vectors is freed later by > swsusp_free(). That perhaps explains why we do not see any crash. I was trying to figure out if we end up initialising VBAR_EL2 before we "return" from swsusp_arch_suspend() and free the reserved pages. However, it looks like we run _cpu_resume() instead of cpu_resume() so I still can't tell why this hasn't exploded. AFAICT, the active hyp vectors will have been freed (and possibly poisoned) long before KVM initialises. Speaking off-list to Mark R, he pointed me at some old rework he had for all of this: https://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git/log/?h=arm64/suspend/cleanup one of the patches there is very similar (identical?) to this one, but his series gets us to a point where we _do_ resume at cpu_resume() and, tbh, the whole thing ends up making a lot more sense. If somebody could dust off that two-year old (!) stack, that would be great. Will