diff mbox series

[03/18] arm64: hyp-stub: Move elx_sync into the vectors

Message ID 20210527150526.271941-4-pasha.tatashin@soleen.com (mailing list archive)
State New, archived
Headers show
Series arm64: MMU enabled kexec relocation | expand

Commit Message

Pasha Tatashin May 27, 2021, 3:05 p.m. UTC
The hyp-stub's elx_sync code fits in the vector.

With this, all of the hyp-stubs behaviour is contained in its vectors.
This lets kexec and hibernate copy the hyp-stub when they need its
behaviour, instead of re-implementing it.

Co-developed-by: James Morse <james.morse@arm.com>
Signed-off-by: Pavel Tatashin <pasha.tatashin@soleen.com>
---
 arch/arm64/kernel/hyp-stub.S | 64 +++++++++++++++++++-----------------
 1 file changed, 33 insertions(+), 31 deletions(-)

Comments

Marc Zyngier May 27, 2021, 3:54 p.m. UTC | #1
On Thu, 27 May 2021 16:05:11 +0100,
Pavel Tatashin <pasha.tatashin@soleen.com> wrote:
> 
> The hyp-stub's elx_sync code fits in the vector.
> 
> With this, all of the hyp-stubs behaviour is contained in its vectors.
> This lets kexec and hibernate copy the hyp-stub when they need its
> behaviour, instead of re-implementing it.
> 
> Co-developed-by: James Morse <james.morse@arm.com>
> Signed-off-by: Pavel Tatashin <pasha.tatashin@soleen.com>
> ---
>  arch/arm64/kernel/hyp-stub.S | 64 +++++++++++++++++++-----------------
>  1 file changed, 33 insertions(+), 31 deletions(-)
> 
> diff --git a/arch/arm64/kernel/hyp-stub.S b/arch/arm64/kernel/hyp-stub.S
> index 18a97bee3779..86af6c4e52b9 100644
> --- a/arch/arm64/kernel/hyp-stub.S
> +++ b/arch/arm64/kernel/hyp-stub.S
> @@ -21,6 +21,37 @@ SYM_CODE_START_LOCAL(\label)
>  	.align 7
>  	b	\label
>  SYM_CODE_END(\label)
> +.endm
> +
> +.macro elx_sync_vector	label
> +SYM_CODE_START_LOCAL(\label)
> +	.align 7
> +	cmp	x0, #HVC_SET_VECTORS
> +	b.ne	1f
> +	msr	vbar_el2, x1
> +	b	9f
> +
> +1:	cmp	x0, #HVC_VHE_RESTART
> +	b.eq	mutate_to_vhe

Now that this has turned into a macro, what are the guarantees that
mutate_to_vhe will be within reach of the site where this macro is
expanded? It does work here, but what about the other expansion sites
that will show up later in the series?

What was wrong with directly branching to the original call site?
Nothing in the commit message explains it.

Thanks,

	M.
Pasha Tatashin May 27, 2021, 9:23 p.m. UTC | #2
On Thu, May 27, 2021 at 11:54 AM Marc Zyngier <maz@kernel.org> wrote:
>
> On Thu, 27 May 2021 16:05:11 +0100,
> Pavel Tatashin <pasha.tatashin@soleen.com> wrote:
> >
> > The hyp-stub's elx_sync code fits in the vector.
> >
> > With this, all of the hyp-stubs behaviour is contained in its vectors.
> > This lets kexec and hibernate copy the hyp-stub when they need its
> > behaviour, instead of re-implementing it.
> >
> > Co-developed-by: James Morse <james.morse@arm.com>
> > Signed-off-by: Pavel Tatashin <pasha.tatashin@soleen.com>
> > ---
> >  arch/arm64/kernel/hyp-stub.S | 64 +++++++++++++++++++-----------------
> >  1 file changed, 33 insertions(+), 31 deletions(-)
> >
> > diff --git a/arch/arm64/kernel/hyp-stub.S b/arch/arm64/kernel/hyp-stub.S
> > index 18a97bee3779..86af6c4e52b9 100644
> > --- a/arch/arm64/kernel/hyp-stub.S
> > +++ b/arch/arm64/kernel/hyp-stub.S
> > @@ -21,6 +21,37 @@ SYM_CODE_START_LOCAL(\label)
> >       .align 7
> >       b       \label
> >  SYM_CODE_END(\label)
> > +.endm
> > +
> > +.macro elx_sync_vector       label
> > +SYM_CODE_START_LOCAL(\label)
> > +     .align 7
> > +     cmp     x0, #HVC_SET_VECTORS
> > +     b.ne    1f
> > +     msr     vbar_el2, x1
> > +     b       9f
> > +
> > +1:   cmp     x0, #HVC_VHE_RESTART
> > +     b.eq    mutate_to_vhe
>
> Now that this has turned into a macro, what are the guarantees that
> mutate_to_vhe will be within reach of the site where this macro is
> expanded? It does work here, but what about the other expansion sites
> that will show up later in the series?
>
> What was wrong with directly branching to the original call site?
> Nothing in the commit message explains it.

Hi Marc,

I need to explain this better in the commit log. Later in the series
we create our own vector copy that is outside of the old and new
kernel so it does not get overwritten during kexec relocation. When
VHE is enabled, the vector is passed so we can switch to el2 before
jumping to the new kernel.

arm64_relocate_new_kernel() which performs the relocation runs with
MMU being enabled until relocation is done, after that disables MMU
and if vectors are passed performs:

         mov     x0, #HVC_SOFT_RESTART
         hvc     #0         /* Jumps from el2 */

It cannot call mutate_to_vhe because #HVC_VHE_RESTART is not used
here. But, if it had to it would not work as we cannot return to the
old kernel text after relocation.

Thanks,
Pasha

>
> Thanks,
>
>         M.
>
> --
> Without deviation from the norm, progress is not possible.
Marc Zyngier June 1, 2021, 12:22 p.m. UTC | #3
On Thu, 27 May 2021 22:23:22 +0100,
Pavel Tatashin <pasha.tatashin@soleen.com> wrote:
> 
> On Thu, May 27, 2021 at 11:54 AM Marc Zyngier <maz@kernel.org> wrote:
> >
> > On Thu, 27 May 2021 16:05:11 +0100,
> > Pavel Tatashin <pasha.tatashin@soleen.com> wrote:
> > >
> > > The hyp-stub's elx_sync code fits in the vector.
> > >
> > > With this, all of the hyp-stubs behaviour is contained in its vectors.
> > > This lets kexec and hibernate copy the hyp-stub when they need its
> > > behaviour, instead of re-implementing it.
> > >
> > > Co-developed-by: James Morse <james.morse@arm.com>
> > > Signed-off-by: Pavel Tatashin <pasha.tatashin@soleen.com>
> > > ---
> > >  arch/arm64/kernel/hyp-stub.S | 64 +++++++++++++++++++-----------------
> > >  1 file changed, 33 insertions(+), 31 deletions(-)
> > >
> > > diff --git a/arch/arm64/kernel/hyp-stub.S b/arch/arm64/kernel/hyp-stub.S
> > > index 18a97bee3779..86af6c4e52b9 100644
> > > --- a/arch/arm64/kernel/hyp-stub.S
> > > +++ b/arch/arm64/kernel/hyp-stub.S
> > > @@ -21,6 +21,37 @@ SYM_CODE_START_LOCAL(\label)
> > >       .align 7
> > >       b       \label
> > >  SYM_CODE_END(\label)
> > > +.endm
> > > +
> > > +.macro elx_sync_vector       label
> > > +SYM_CODE_START_LOCAL(\label)
> > > +     .align 7
> > > +     cmp     x0, #HVC_SET_VECTORS
> > > +     b.ne    1f
> > > +     msr     vbar_el2, x1
> > > +     b       9f
> > > +
> > > +1:   cmp     x0, #HVC_VHE_RESTART
> > > +     b.eq    mutate_to_vhe
> >
> > Now that this has turned into a macro, what are the guarantees that
> > mutate_to_vhe will be within reach of the site where this macro is
> > expanded? It does work here, but what about the other expansion sites
> > that will show up later in the series?
> >
> > What was wrong with directly branching to the original call site?
> > Nothing in the commit message explains it.
> 
> Hi Marc,
> 
> I need to explain this better in the commit log. Later in the series
> we create our own vector copy that is outside of the old and new
> kernel so it does not get overwritten during kexec relocation. When
> VHE is enabled, the vector is passed so we can switch to el2 before
> jumping to the new kernel.
> 
> arm64_relocate_new_kernel() which performs the relocation runs with
> MMU being enabled until relocation is done, after that disables MMU
> and if vectors are passed performs:
> 
>          mov     x0, #HVC_SOFT_RESTART
>          hvc     #0         /* Jumps from el2 */
> 
> It cannot call mutate_to_vhe because #HVC_VHE_RESTART is not used
> here. But, if it had to it would not work as we cannot return to the
> old kernel text after relocation.

OK, so you are happy with having a dangling branch pointing to
nowhere? Something in me screams that it isn't a good idea, in
general.

If HVC_SOFT_RESTART is all you need, I'd rather you have a small stub
that implements exactly that and nothing else. Feel free to extract it
as a reusable macro if you want.

Thanks,

	M.
Pasha Tatashin June 2, 2021, 1:18 a.m. UTC | #4
> > It cannot call mutate_to_vhe because #HVC_VHE_RESTART is not used
> > here. But, if it had to it would not work as we cannot return to the
> > old kernel text after relocation.
>
> OK, so you are happy with having a dangling branch pointing to
> nowhere? Something in me screams that it isn't a good idea, in
> general.
>
> If HVC_SOFT_RESTART is all you need, I'd rather you have a small stub
> that implements exactly that and nothing else. Feel free to extract it
> as a reusable macro if you want.

Sure, I will add in the next revision.

Thanks,
Pasha
Pasha Tatashin June 8, 2021, 5:46 p.m. UTC | #5
On Tue, Jun 1, 2021 at 9:18 PM Pavel Tatashin <pasha.tatashin@soleen.com> wrote:
>
> > > It cannot call mutate_to_vhe because #HVC_VHE_RESTART is not used
> > > here. But, if it had to it would not work as we cannot return to the
> > > old kernel text after relocation.
> >
> > OK, so you are happy with having a dangling branch pointing to
> > nowhere? Something in me screams that it isn't a good idea, in
> > general.
> >
> > If HVC_SOFT_RESTART is all you need, I'd rather you have a small stub
> > that implements exactly that and nothing else. Feel free to extract it
> > as a reusable macro if you want.

Using macro won't help here to save kernel text. Optimally, we would
want to use only one vector table to reduce kernel text memory usage.
I could do that by overwriting sync entries in
trans_pgd_copy_el2_vectors(). But, that would be ugly, as I would need
to have some specific assumptions about what entries need to be
overwritten. Therefore, I decided to move the vector table that we
currently have in hibernate code, and make it common between kexec and
hibernate; trans_pgd_copy_el2_vectors() will use that table's body to
create copies.

Thanks,
Pasha
diff mbox series

Patch

diff --git a/arch/arm64/kernel/hyp-stub.S b/arch/arm64/kernel/hyp-stub.S
index 18a97bee3779..86af6c4e52b9 100644
--- a/arch/arm64/kernel/hyp-stub.S
+++ b/arch/arm64/kernel/hyp-stub.S
@@ -21,6 +21,37 @@  SYM_CODE_START_LOCAL(\label)
 	.align 7
 	b	\label
 SYM_CODE_END(\label)
+.endm
+
+.macro elx_sync_vector	label
+SYM_CODE_START_LOCAL(\label)
+	.align 7
+	cmp	x0, #HVC_SET_VECTORS
+	b.ne	1f
+	msr	vbar_el2, x1
+	b	9f
+
+1:	cmp	x0, #HVC_VHE_RESTART
+	b.eq	mutate_to_vhe
+
+2:	cmp	x0, #HVC_SOFT_RESTART
+	b.ne	3f
+	mov	x0, x2
+	mov	x2, x4
+	mov	x4, x1
+	mov	x1, x3
+	br	x4				// no return
+
+3:	cmp	x0, #HVC_RESET_VECTORS
+	beq	9f				// Nothing to reset!
+
+	/* Someone called kvm_call_hyp() against the hyp-stub... */
+	mov_q	x0, HVC_STUB_ERR
+	eret
+
+9:	mov	x0, xzr
+	eret
+SYM_CODE_END(\label)
 .endm
 
 	.text
@@ -34,12 +65,12 @@  SYM_CODE_START(__hyp_stub_vectors)
 	invalid_vector	hyp_stub_el2t_fiq_invalid	// FIQ EL2t
 	invalid_vector	hyp_stub_el2t_error_invalid	// Error EL2t
 
-	ventry	elx_sync				// Synchronous EL2h
+	elx_sync_vector	el2h_sync			// Synchronous EL2h
 	invalid_vector	hyp_stub_el2h_irq_invalid	// IRQ EL2h
 	invalid_vector	hyp_stub_el2h_fiq_invalid	// FIQ EL2h
 	invalid_vector	hyp_stub_el2h_error_invalid	// Error EL2h
 
-	ventry	elx_sync				// Synchronous 64-bit EL1
+	elx_sync_vector	el1_sync			// Synchronous 64-bit EL1
 	invalid_vector	hyp_stub_el1_irq_invalid	// IRQ 64-bit EL1
 	invalid_vector	hyp_stub_el1_fiq_invalid	// FIQ 64-bit EL1
 	invalid_vector	hyp_stub_el1_error_invalid	// Error 64-bit EL1
@@ -55,35 +86,6 @@  SYM_CODE_END(__hyp_stub_vectors)
 # Check the __hyp_stub_vectors didn't overflow
 .org . - (__hyp_stub_vectors_end - __hyp_stub_vectors) + SZ_2K
 
-
-SYM_CODE_START_LOCAL(elx_sync)
-	cmp	x0, #HVC_SET_VECTORS
-	b.ne	1f
-	msr	vbar_el2, x1
-	b	9f
-
-1:	cmp	x0, #HVC_VHE_RESTART
-	b.eq	mutate_to_vhe
-
-2:	cmp	x0, #HVC_SOFT_RESTART
-	b.ne	3f
-	mov	x0, x2
-	mov	x2, x4
-	mov	x4, x1
-	mov	x1, x3
-	br	x4				// no return
-
-3:	cmp	x0, #HVC_RESET_VECTORS
-	beq	9f				// Nothing to reset!
-
-	/* Someone called kvm_call_hyp() against the hyp-stub... */
-	mov_q	x0, HVC_STUB_ERR
-	eret
-
-9:	mov	x0, xzr
-	eret
-SYM_CODE_END(elx_sync)
-
 // nVHE? No way! Give me the real thing!
 SYM_CODE_START_LOCAL(mutate_to_vhe)
 	// Sanity check: MMU *must* be off