All of lore.kernel.org
 help / color / mirror / Atom feed
From: Quentin Perret <qperret@google.com>
To: Marc Zyngier <maz@kernel.org>
Cc: David Brazdil <dbrazdil@google.com>,
	Catalin Marinas <catalin.marinas@arm.com>,
	James Morse <james.morse@arm.com>,
	Julien Thierry <julien.thierry.kdev@gmail.com>,
	Suzuki K Poulose <suzuki.poulose@arm.com>,
	Will Deacon <will@kernel.org>,
	kvmarm@lists.cs.columbia.edu,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH 02/15] arm64: kvm: Formalize host-hyp hypcall ABI
Date: Thu, 7 May 2020 14:33:20 +0100	[thread overview]
Message-ID: <20200507133320.GA16899@google.com> (raw)
In-Reply-To: <87d07fj3g9.wl-maz@kernel.org>

Hey Marc,

On Thursday 07 May 2020 at 14:10:30 (+0100), Marc Zyngier wrote:
> Hi David, Quentin,
> 
> On Thu, 30 Apr 2020 15:48:18 +0100,
> David Brazdil <dbrazdil@google.com> wrote:
> > 
> > From: Quentin Perret <qperret@google.com>
> > 
> > In preparation for removing the hyp code from the TCB, convert the current
> 
> nit: Unless we have a different interpretation of the TCB acronym, I
> think you want to remove anything *but* the EL2 code from the TCB.

Argh! Right... This should have been 'removing the /host/ code' :-)

<snip>
> > diff --git a/arch/arm64/include/asm/kvm_host_hypercalls.h b/arch/arm64/include/asm/kvm_host_hypercalls.h
> > new file mode 100644
> > index 000000000000..af8ad505d816
> > --- /dev/null
> > +++ b/arch/arm64/include/asm/kvm_host_hypercalls.h
> > @@ -0,0 +1,62 @@
> > +/* SPDX-License-Identifier: GPL-2.0-only */
> > +/*
> > + * Copyright (C) 2020 Google, inc
> > + */
> > +
> > +#ifndef __KVM_HOST_HCALL
> > +#define __KVM_HOST_HCALL(x)
> > +#endif
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___kvm_enable_ssbs		0
> > +__KVM_HOST_HCALL(__kvm_enable_ssbs)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___kvm_get_mdcr_el2		1
> > +__KVM_HOST_HCALL(__kvm_get_mdcr_el2)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___kvm_timer_set_cntvoff	2
> > +__KVM_HOST_HCALL(__kvm_timer_set_cntvoff)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___kvm_tlb_flush_local_vmid	3
> > +__KVM_HOST_HCALL(__kvm_tlb_flush_local_vmid)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___kvm_flush_vm_context	4
> > +__KVM_HOST_HCALL(__kvm_flush_vm_context)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___kvm_vcpu_run_nvhe		5
> > +__KVM_HOST_HCALL(__kvm_vcpu_run_nvhe)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___kvm_tlb_flush_vmid		6
> > +__KVM_HOST_HCALL(__kvm_tlb_flush_vmid)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___kvm_tlb_flush_vmid_ipa	7
> > +__KVM_HOST_HCALL(__kvm_tlb_flush_vmid_ipa)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___vgic_v3_init_lrs		8
> > +__KVM_HOST_HCALL(__vgic_v3_init_lrs)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___vgic_v3_get_ich_vtr_el2	9
> > +__KVM_HOST_HCALL(__vgic_v3_get_ich_vtr_el2)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___vgic_v3_write_vmcr		10
> > +__KVM_HOST_HCALL(__vgic_v3_write_vmcr)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___vgic_v3_restore_aprs	11
> > +__KVM_HOST_HCALL(__vgic_v3_restore_aprs)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___vgic_v3_read_vmcr		12
> > +__KVM_HOST_HCALL(__vgic_v3_read_vmcr)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___vgic_v3_save_aprs		13
> > +__KVM_HOST_HCALL(__vgic_v3_save_aprs)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX_SIZE				14
> 
> This whole thing screams "enum" into my ears. Having to maintain these
> as #defines feels like a pain, specially if the numbers are never used
> in assembly code. (and for that, we have asm-offset.h).

This is essentially inspired from the various 'unistd.h' files we have
in the kernel, e.g. include/uapi/asm-generic/unistd.h, which have
exactly this type of construct. So, this was really just for consistency,
but no strong opinion from me.

> 
> > +
> > +/* XXX - Arbitrary offset for KVM-related hypercalls */
> > +#define __KVM_HOST_HCALL_BASE_SHIFT 8
> > +#define __KVM_HOST_HCALL_BASE (1ULL << __KVM_HOST_HCALL_BASE_SHIFT)
> > +#define __KVM_HOST_HCALL_END (__KVM_HOST_HCALL_BASE + \
> > +			      __KVM_HOST_HCALL_TABLE_IDX_SIZE)
> 
> I don't really get what is this offset for. It is too small to be used
> to skip the stub hypercalls (you'd need to start at 0x1000).

Oh, OK. I assumed anything above HVC_STUB_HCALL_NR would be fine. But
yes, this offset is really arbitrary, so if 0x1000 is better then that
totally works. For my education, where is that 0x1000 coming from ?

> Given
> that you store the whole thing in an array, you're wasting some
> memory. I'm sure you have a good story for it though! ;-)

Note that the array's length is __KVM_HOST_HCALL_TABLE_IDX_SIZE, which
doesn't include the offset, so we shouldn't be wasting memory here.

> > +
> > +/* Hypercall number = kvm offset + table idx */
> > +#define KVM_HOST_HCALL_NR(name) (__KVM_HOST_HCALL_TABLE_IDX_##name + \
> > +				 __KVM_HOST_HCALL_BASE)
> > diff --git a/arch/arm64/kvm/hyp/Makefile b/arch/arm64/kvm/hyp/Makefile
> > index 8c9880783839..29e2b2cd2fbc 100644
> > --- a/arch/arm64/kvm/hyp/Makefile
> > +++ b/arch/arm64/kvm/hyp/Makefile
> > @@ -9,7 +9,7 @@ ccflags-y += -fno-stack-protector -DDISABLE_BRANCH_PROFILING \
> >  obj-$(CONFIG_KVM) += hyp.o
> >  
> >  hyp-y := vgic-v3-sr.o timer-sr.o aarch32.o vgic-v2-cpuif-proxy.o sysreg-sr.o \
> > -	 debug-sr.o entry.o switch.o fpsimd.o tlb.o hyp-entry.o
> > +	 debug-sr.o entry.o switch.o fpsimd.o tlb.o host_hypercall.o hyp-entry.o
> >  
> >  # KVM code is run at a different exception code with a different map, so
> >  # compiler instrumentation that inserts callbacks or checks into the code may
> > diff --git a/arch/arm64/kvm/hyp/host_hypercall.c b/arch/arm64/kvm/hyp/host_hypercall.c
> > new file mode 100644
> > index 000000000000..6b31310f36a8
> > --- /dev/null
> > +++ b/arch/arm64/kvm/hyp/host_hypercall.c
> > @@ -0,0 +1,22 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/*
> > + * Copyright (C) 2020 Google, inc
> > + */
> > +
> > +#include <asm/kvm_hyp.h>
> > +
> > +typedef long (*kvm_hcall_fn_t)(void);
> > +
> > +static long __hyp_text kvm_hc_ni(void)
> > +{
> > +       return -ENOSYS;
> > +}
> > +
> > +#undef __KVM_HOST_HCALL
> > +#define __KVM_HOST_HCALL(name) \
> > +	[__KVM_HOST_HCALL_TABLE_IDX_##name] = (long (*)(void))name,
> > +
> > +const kvm_hcall_fn_t kvm_hcall_table[__KVM_HOST_HCALL_TABLE_IDX_SIZE] = {
> > +	[0 ... __KVM_HOST_HCALL_TABLE_IDX_SIZE-1] = kvm_hc_ni,
> > +#include <asm/kvm_host_hypercalls.h>
> > +};
> 
> Cunning. At the same time, if you can do this once, you can do it
> twice, and generating the __KVM_HOST_HCALL_TABLE_IDX_* as an enum
> should be pretty easy, and could live in its own include file.

Right, and that again is inspired from the arm64 syscall table (see
arch/arm64/kernel/sys.c). So the first intention was to keep things
consistent. But again, no strong opinion :)

> > diff --git a/arch/arm64/kvm/hyp/hyp-entry.S b/arch/arm64/kvm/hyp/hyp-entry.S
> > index c2a13ab3c471..1a51a0958504 100644
> > --- a/arch/arm64/kvm/hyp/hyp-entry.S
> > +++ b/arch/arm64/kvm/hyp/hyp-entry.S
> > @@ -13,6 +13,7 @@
> >  #include <asm/kvm_arm.h>
> >  #include <asm/kvm_asm.h>
> >  #include <asm/kvm_mmu.h>
> > +#include <asm/kvm_host_hypercalls.h>
> >  #include <asm/mmu.h>
> >  
> >  	.text
> > @@ -21,17 +22,26 @@
> >  .macro do_el2_call
> >  	/*
> >  	 * Shuffle the parameters before calling the function
> > -	 * pointed to in x0. Assumes parameters in x[1,2,3].
> > +	 * pointed to in x0. Assumes parameters in x[1,2,3,4,5,6].
> >  	 */
> >  	str	lr, [sp, #-16]!
> >  	mov	lr, x0
> >  	mov	x0, x1
> >  	mov	x1, x2
> >  	mov	x2, x3
> > +	mov	x3, x4
> > +	mov	x4, x5
> > +	mov	x5, x6
> 
> Has any function changed prototype as part of this patch that they'd
> require this change? It doesn't look like it. I guess this should be
> part of another patch.

Ack, this isn't needed just yet so we should split that out.

> 
> >  	blr	lr
> >  	ldr	lr, [sp], #16
> >  .endm
> >  
> > +/* kern_hyp_va(lm_alias(ksym)) */
> > +.macro ksym_hyp_va ksym, lm_offset
> > +	sub	\ksym, \ksym, \lm_offset
> > +	kern_hyp_va	\ksym
> > +.endm
> > +
> >  el1_sync:				// Guest trapped into EL2
> >  
> >  	mrs	x0, esr_el2
> > @@ -66,10 +76,32 @@ el1_sync:				// Guest trapped into EL2
> >  	br	x5
> >  
> >  1:
> > +	/* Check if the hcall number is valid */
> > +	cmp	x0, #__KVM_HOST_HCALL_BASE
> > +	b.lt	2f
> > +	cmp	x0, #__KVM_HOST_HCALL_END
> > +	b.lt	3f
> > +2:
> > +	mov	x0, -ENOSYS
> > +	eret
> > +
> > +3:
> > +	/* Compute lm_alias() offset in x9 */
> > +	ldr_l	x9, kimage_voffset
> > +	ldr_l	x10, physvirt_offset
> > +	add	x9, x9, x10
> > +
> > +	/* Find hcall function pointer in the table */
> > +	ldr	x10, =kvm_hcall_table
> > +	ksym_hyp_va	x10, x9
> 
> Can't kvm_hcall_table be referenced with adr or adr_l? It'd certainly
> be nice to avoid the extra load for something that is essentially a
> build-time constant.

In fact David already has a nice patch that transforms the whole thing
in a jump table, which is much nicer. I'll let him share the details :)

> Another thing that could be improved is to keep the lm_alias offset
> somewhere, saving one load per entry. Not a huge deal.

Ack.

> > +	sub	x0, x0, #__KVM_HOST_HCALL_BASE
> > +	add	x0, x10, x0, lsl 3
> 
> The usual convention for immediate is to prefix them with #.

Noted, thanks.

> > +	ldr	x0, [x0]
> > +	ksym_hyp_va	x0, x9
> > +
> >  	/*
> >  	 * Perform the EL2 call
> >  	 */
> > -	kern_hyp_va	x0
> >  	do_el2_call
> >  
> >  	eret
> > -- 
> > 2.26.1
> > 
> > 

Thanks for the review!
Quentin

WARNING: multiple messages have this Message-ID (diff)
From: Quentin Perret <qperret@google.com>
To: Marc Zyngier <maz@kernel.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>,
	linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	Will Deacon <will@kernel.org>,
	kvmarm@lists.cs.columbia.edu
Subject: Re: [PATCH 02/15] arm64: kvm: Formalize host-hyp hypcall ABI
Date: Thu, 7 May 2020 14:33:20 +0100	[thread overview]
Message-ID: <20200507133320.GA16899@google.com> (raw)
In-Reply-To: <87d07fj3g9.wl-maz@kernel.org>

Hey Marc,

On Thursday 07 May 2020 at 14:10:30 (+0100), Marc Zyngier wrote:
> Hi David, Quentin,
> 
> On Thu, 30 Apr 2020 15:48:18 +0100,
> David Brazdil <dbrazdil@google.com> wrote:
> > 
> > From: Quentin Perret <qperret@google.com>
> > 
> > In preparation for removing the hyp code from the TCB, convert the current
> 
> nit: Unless we have a different interpretation of the TCB acronym, I
> think you want to remove anything *but* the EL2 code from the TCB.

Argh! Right... This should have been 'removing the /host/ code' :-)

<snip>
> > diff --git a/arch/arm64/include/asm/kvm_host_hypercalls.h b/arch/arm64/include/asm/kvm_host_hypercalls.h
> > new file mode 100644
> > index 000000000000..af8ad505d816
> > --- /dev/null
> > +++ b/arch/arm64/include/asm/kvm_host_hypercalls.h
> > @@ -0,0 +1,62 @@
> > +/* SPDX-License-Identifier: GPL-2.0-only */
> > +/*
> > + * Copyright (C) 2020 Google, inc
> > + */
> > +
> > +#ifndef __KVM_HOST_HCALL
> > +#define __KVM_HOST_HCALL(x)
> > +#endif
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___kvm_enable_ssbs		0
> > +__KVM_HOST_HCALL(__kvm_enable_ssbs)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___kvm_get_mdcr_el2		1
> > +__KVM_HOST_HCALL(__kvm_get_mdcr_el2)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___kvm_timer_set_cntvoff	2
> > +__KVM_HOST_HCALL(__kvm_timer_set_cntvoff)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___kvm_tlb_flush_local_vmid	3
> > +__KVM_HOST_HCALL(__kvm_tlb_flush_local_vmid)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___kvm_flush_vm_context	4
> > +__KVM_HOST_HCALL(__kvm_flush_vm_context)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___kvm_vcpu_run_nvhe		5
> > +__KVM_HOST_HCALL(__kvm_vcpu_run_nvhe)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___kvm_tlb_flush_vmid		6
> > +__KVM_HOST_HCALL(__kvm_tlb_flush_vmid)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___kvm_tlb_flush_vmid_ipa	7
> > +__KVM_HOST_HCALL(__kvm_tlb_flush_vmid_ipa)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___vgic_v3_init_lrs		8
> > +__KVM_HOST_HCALL(__vgic_v3_init_lrs)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___vgic_v3_get_ich_vtr_el2	9
> > +__KVM_HOST_HCALL(__vgic_v3_get_ich_vtr_el2)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___vgic_v3_write_vmcr		10
> > +__KVM_HOST_HCALL(__vgic_v3_write_vmcr)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___vgic_v3_restore_aprs	11
> > +__KVM_HOST_HCALL(__vgic_v3_restore_aprs)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___vgic_v3_read_vmcr		12
> > +__KVM_HOST_HCALL(__vgic_v3_read_vmcr)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___vgic_v3_save_aprs		13
> > +__KVM_HOST_HCALL(__vgic_v3_save_aprs)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX_SIZE				14
> 
> This whole thing screams "enum" into my ears. Having to maintain these
> as #defines feels like a pain, specially if the numbers are never used
> in assembly code. (and for that, we have asm-offset.h).

This is essentially inspired from the various 'unistd.h' files we have
in the kernel, e.g. include/uapi/asm-generic/unistd.h, which have
exactly this type of construct. So, this was really just for consistency,
but no strong opinion from me.

> 
> > +
> > +/* XXX - Arbitrary offset for KVM-related hypercalls */
> > +#define __KVM_HOST_HCALL_BASE_SHIFT 8
> > +#define __KVM_HOST_HCALL_BASE (1ULL << __KVM_HOST_HCALL_BASE_SHIFT)
> > +#define __KVM_HOST_HCALL_END (__KVM_HOST_HCALL_BASE + \
> > +			      __KVM_HOST_HCALL_TABLE_IDX_SIZE)
> 
> I don't really get what is this offset for. It is too small to be used
> to skip the stub hypercalls (you'd need to start at 0x1000).

Oh, OK. I assumed anything above HVC_STUB_HCALL_NR would be fine. But
yes, this offset is really arbitrary, so if 0x1000 is better then that
totally works. For my education, where is that 0x1000 coming from ?

> Given
> that you store the whole thing in an array, you're wasting some
> memory. I'm sure you have a good story for it though! ;-)

Note that the array's length is __KVM_HOST_HCALL_TABLE_IDX_SIZE, which
doesn't include the offset, so we shouldn't be wasting memory here.

> > +
> > +/* Hypercall number = kvm offset + table idx */
> > +#define KVM_HOST_HCALL_NR(name) (__KVM_HOST_HCALL_TABLE_IDX_##name + \
> > +				 __KVM_HOST_HCALL_BASE)
> > diff --git a/arch/arm64/kvm/hyp/Makefile b/arch/arm64/kvm/hyp/Makefile
> > index 8c9880783839..29e2b2cd2fbc 100644
> > --- a/arch/arm64/kvm/hyp/Makefile
> > +++ b/arch/arm64/kvm/hyp/Makefile
> > @@ -9,7 +9,7 @@ ccflags-y += -fno-stack-protector -DDISABLE_BRANCH_PROFILING \
> >  obj-$(CONFIG_KVM) += hyp.o
> >  
> >  hyp-y := vgic-v3-sr.o timer-sr.o aarch32.o vgic-v2-cpuif-proxy.o sysreg-sr.o \
> > -	 debug-sr.o entry.o switch.o fpsimd.o tlb.o hyp-entry.o
> > +	 debug-sr.o entry.o switch.o fpsimd.o tlb.o host_hypercall.o hyp-entry.o
> >  
> >  # KVM code is run at a different exception code with a different map, so
> >  # compiler instrumentation that inserts callbacks or checks into the code may
> > diff --git a/arch/arm64/kvm/hyp/host_hypercall.c b/arch/arm64/kvm/hyp/host_hypercall.c
> > new file mode 100644
> > index 000000000000..6b31310f36a8
> > --- /dev/null
> > +++ b/arch/arm64/kvm/hyp/host_hypercall.c
> > @@ -0,0 +1,22 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/*
> > + * Copyright (C) 2020 Google, inc
> > + */
> > +
> > +#include <asm/kvm_hyp.h>
> > +
> > +typedef long (*kvm_hcall_fn_t)(void);
> > +
> > +static long __hyp_text kvm_hc_ni(void)
> > +{
> > +       return -ENOSYS;
> > +}
> > +
> > +#undef __KVM_HOST_HCALL
> > +#define __KVM_HOST_HCALL(name) \
> > +	[__KVM_HOST_HCALL_TABLE_IDX_##name] = (long (*)(void))name,
> > +
> > +const kvm_hcall_fn_t kvm_hcall_table[__KVM_HOST_HCALL_TABLE_IDX_SIZE] = {
> > +	[0 ... __KVM_HOST_HCALL_TABLE_IDX_SIZE-1] = kvm_hc_ni,
> > +#include <asm/kvm_host_hypercalls.h>
> > +};
> 
> Cunning. At the same time, if you can do this once, you can do it
> twice, and generating the __KVM_HOST_HCALL_TABLE_IDX_* as an enum
> should be pretty easy, and could live in its own include file.

Right, and that again is inspired from the arm64 syscall table (see
arch/arm64/kernel/sys.c). So the first intention was to keep things
consistent. But again, no strong opinion :)

> > diff --git a/arch/arm64/kvm/hyp/hyp-entry.S b/arch/arm64/kvm/hyp/hyp-entry.S
> > index c2a13ab3c471..1a51a0958504 100644
> > --- a/arch/arm64/kvm/hyp/hyp-entry.S
> > +++ b/arch/arm64/kvm/hyp/hyp-entry.S
> > @@ -13,6 +13,7 @@
> >  #include <asm/kvm_arm.h>
> >  #include <asm/kvm_asm.h>
> >  #include <asm/kvm_mmu.h>
> > +#include <asm/kvm_host_hypercalls.h>
> >  #include <asm/mmu.h>
> >  
> >  	.text
> > @@ -21,17 +22,26 @@
> >  .macro do_el2_call
> >  	/*
> >  	 * Shuffle the parameters before calling the function
> > -	 * pointed to in x0. Assumes parameters in x[1,2,3].
> > +	 * pointed to in x0. Assumes parameters in x[1,2,3,4,5,6].
> >  	 */
> >  	str	lr, [sp, #-16]!
> >  	mov	lr, x0
> >  	mov	x0, x1
> >  	mov	x1, x2
> >  	mov	x2, x3
> > +	mov	x3, x4
> > +	mov	x4, x5
> > +	mov	x5, x6
> 
> Has any function changed prototype as part of this patch that they'd
> require this change? It doesn't look like it. I guess this should be
> part of another patch.

Ack, this isn't needed just yet so we should split that out.

> 
> >  	blr	lr
> >  	ldr	lr, [sp], #16
> >  .endm
> >  
> > +/* kern_hyp_va(lm_alias(ksym)) */
> > +.macro ksym_hyp_va ksym, lm_offset
> > +	sub	\ksym, \ksym, \lm_offset
> > +	kern_hyp_va	\ksym
> > +.endm
> > +
> >  el1_sync:				// Guest trapped into EL2
> >  
> >  	mrs	x0, esr_el2
> > @@ -66,10 +76,32 @@ el1_sync:				// Guest trapped into EL2
> >  	br	x5
> >  
> >  1:
> > +	/* Check if the hcall number is valid */
> > +	cmp	x0, #__KVM_HOST_HCALL_BASE
> > +	b.lt	2f
> > +	cmp	x0, #__KVM_HOST_HCALL_END
> > +	b.lt	3f
> > +2:
> > +	mov	x0, -ENOSYS
> > +	eret
> > +
> > +3:
> > +	/* Compute lm_alias() offset in x9 */
> > +	ldr_l	x9, kimage_voffset
> > +	ldr_l	x10, physvirt_offset
> > +	add	x9, x9, x10
> > +
> > +	/* Find hcall function pointer in the table */
> > +	ldr	x10, =kvm_hcall_table
> > +	ksym_hyp_va	x10, x9
> 
> Can't kvm_hcall_table be referenced with adr or adr_l? It'd certainly
> be nice to avoid the extra load for something that is essentially a
> build-time constant.

In fact David already has a nice patch that transforms the whole thing
in a jump table, which is much nicer. I'll let him share the details :)

> Another thing that could be improved is to keep the lm_alias offset
> somewhere, saving one load per entry. Not a huge deal.

Ack.

> > +	sub	x0, x0, #__KVM_HOST_HCALL_BASE
> > +	add	x0, x10, x0, lsl 3
> 
> The usual convention for immediate is to prefix them with #.

Noted, thanks.

> > +	ldr	x0, [x0]
> > +	ksym_hyp_va	x0, x9
> > +
> >  	/*
> >  	 * Perform the EL2 call
> >  	 */
> > -	kern_hyp_va	x0
> >  	do_el2_call
> >  
> >  	eret
> > -- 
> > 2.26.1
> > 
> > 

Thanks for the review!
Quentin
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

WARNING: multiple messages have this Message-ID (diff)
From: Quentin Perret <qperret@google.com>
To: Marc Zyngier <maz@kernel.org>
Cc: Suzuki K Poulose <suzuki.poulose@arm.com>,
	Catalin Marinas <catalin.marinas@arm.com>,
	linux-kernel@vger.kernel.org, James Morse <james.morse@arm.com>,
	linux-arm-kernel@lists.infradead.org,
	David Brazdil <dbrazdil@google.com>,
	Will Deacon <will@kernel.org>,
	kvmarm@lists.cs.columbia.edu,
	Julien Thierry <julien.thierry.kdev@gmail.com>
Subject: Re: [PATCH 02/15] arm64: kvm: Formalize host-hyp hypcall ABI
Date: Thu, 7 May 2020 14:33:20 +0100	[thread overview]
Message-ID: <20200507133320.GA16899@google.com> (raw)
In-Reply-To: <87d07fj3g9.wl-maz@kernel.org>

Hey Marc,

On Thursday 07 May 2020 at 14:10:30 (+0100), Marc Zyngier wrote:
> Hi David, Quentin,
> 
> On Thu, 30 Apr 2020 15:48:18 +0100,
> David Brazdil <dbrazdil@google.com> wrote:
> > 
> > From: Quentin Perret <qperret@google.com>
> > 
> > In preparation for removing the hyp code from the TCB, convert the current
> 
> nit: Unless we have a different interpretation of the TCB acronym, I
> think you want to remove anything *but* the EL2 code from the TCB.

Argh! Right... This should have been 'removing the /host/ code' :-)

<snip>
> > diff --git a/arch/arm64/include/asm/kvm_host_hypercalls.h b/arch/arm64/include/asm/kvm_host_hypercalls.h
> > new file mode 100644
> > index 000000000000..af8ad505d816
> > --- /dev/null
> > +++ b/arch/arm64/include/asm/kvm_host_hypercalls.h
> > @@ -0,0 +1,62 @@
> > +/* SPDX-License-Identifier: GPL-2.0-only */
> > +/*
> > + * Copyright (C) 2020 Google, inc
> > + */
> > +
> > +#ifndef __KVM_HOST_HCALL
> > +#define __KVM_HOST_HCALL(x)
> > +#endif
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___kvm_enable_ssbs		0
> > +__KVM_HOST_HCALL(__kvm_enable_ssbs)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___kvm_get_mdcr_el2		1
> > +__KVM_HOST_HCALL(__kvm_get_mdcr_el2)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___kvm_timer_set_cntvoff	2
> > +__KVM_HOST_HCALL(__kvm_timer_set_cntvoff)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___kvm_tlb_flush_local_vmid	3
> > +__KVM_HOST_HCALL(__kvm_tlb_flush_local_vmid)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___kvm_flush_vm_context	4
> > +__KVM_HOST_HCALL(__kvm_flush_vm_context)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___kvm_vcpu_run_nvhe		5
> > +__KVM_HOST_HCALL(__kvm_vcpu_run_nvhe)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___kvm_tlb_flush_vmid		6
> > +__KVM_HOST_HCALL(__kvm_tlb_flush_vmid)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___kvm_tlb_flush_vmid_ipa	7
> > +__KVM_HOST_HCALL(__kvm_tlb_flush_vmid_ipa)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___vgic_v3_init_lrs		8
> > +__KVM_HOST_HCALL(__vgic_v3_init_lrs)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___vgic_v3_get_ich_vtr_el2	9
> > +__KVM_HOST_HCALL(__vgic_v3_get_ich_vtr_el2)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___vgic_v3_write_vmcr		10
> > +__KVM_HOST_HCALL(__vgic_v3_write_vmcr)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___vgic_v3_restore_aprs	11
> > +__KVM_HOST_HCALL(__vgic_v3_restore_aprs)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___vgic_v3_read_vmcr		12
> > +__KVM_HOST_HCALL(__vgic_v3_read_vmcr)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX___vgic_v3_save_aprs		13
> > +__KVM_HOST_HCALL(__vgic_v3_save_aprs)
> > +
> > +#define __KVM_HOST_HCALL_TABLE_IDX_SIZE				14
> 
> This whole thing screams "enum" into my ears. Having to maintain these
> as #defines feels like a pain, specially if the numbers are never used
> in assembly code. (and for that, we have asm-offset.h).

This is essentially inspired from the various 'unistd.h' files we have
in the kernel, e.g. include/uapi/asm-generic/unistd.h, which have
exactly this type of construct. So, this was really just for consistency,
but no strong opinion from me.

> 
> > +
> > +/* XXX - Arbitrary offset for KVM-related hypercalls */
> > +#define __KVM_HOST_HCALL_BASE_SHIFT 8
> > +#define __KVM_HOST_HCALL_BASE (1ULL << __KVM_HOST_HCALL_BASE_SHIFT)
> > +#define __KVM_HOST_HCALL_END (__KVM_HOST_HCALL_BASE + \
> > +			      __KVM_HOST_HCALL_TABLE_IDX_SIZE)
> 
> I don't really get what is this offset for. It is too small to be used
> to skip the stub hypercalls (you'd need to start at 0x1000).

Oh, OK. I assumed anything above HVC_STUB_HCALL_NR would be fine. But
yes, this offset is really arbitrary, so if 0x1000 is better then that
totally works. For my education, where is that 0x1000 coming from ?

> Given
> that you store the whole thing in an array, you're wasting some
> memory. I'm sure you have a good story for it though! ;-)

Note that the array's length is __KVM_HOST_HCALL_TABLE_IDX_SIZE, which
doesn't include the offset, so we shouldn't be wasting memory here.

> > +
> > +/* Hypercall number = kvm offset + table idx */
> > +#define KVM_HOST_HCALL_NR(name) (__KVM_HOST_HCALL_TABLE_IDX_##name + \
> > +				 __KVM_HOST_HCALL_BASE)
> > diff --git a/arch/arm64/kvm/hyp/Makefile b/arch/arm64/kvm/hyp/Makefile
> > index 8c9880783839..29e2b2cd2fbc 100644
> > --- a/arch/arm64/kvm/hyp/Makefile
> > +++ b/arch/arm64/kvm/hyp/Makefile
> > @@ -9,7 +9,7 @@ ccflags-y += -fno-stack-protector -DDISABLE_BRANCH_PROFILING \
> >  obj-$(CONFIG_KVM) += hyp.o
> >  
> >  hyp-y := vgic-v3-sr.o timer-sr.o aarch32.o vgic-v2-cpuif-proxy.o sysreg-sr.o \
> > -	 debug-sr.o entry.o switch.o fpsimd.o tlb.o hyp-entry.o
> > +	 debug-sr.o entry.o switch.o fpsimd.o tlb.o host_hypercall.o hyp-entry.o
> >  
> >  # KVM code is run at a different exception code with a different map, so
> >  # compiler instrumentation that inserts callbacks or checks into the code may
> > diff --git a/arch/arm64/kvm/hyp/host_hypercall.c b/arch/arm64/kvm/hyp/host_hypercall.c
> > new file mode 100644
> > index 000000000000..6b31310f36a8
> > --- /dev/null
> > +++ b/arch/arm64/kvm/hyp/host_hypercall.c
> > @@ -0,0 +1,22 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/*
> > + * Copyright (C) 2020 Google, inc
> > + */
> > +
> > +#include <asm/kvm_hyp.h>
> > +
> > +typedef long (*kvm_hcall_fn_t)(void);
> > +
> > +static long __hyp_text kvm_hc_ni(void)
> > +{
> > +       return -ENOSYS;
> > +}
> > +
> > +#undef __KVM_HOST_HCALL
> > +#define __KVM_HOST_HCALL(name) \
> > +	[__KVM_HOST_HCALL_TABLE_IDX_##name] = (long (*)(void))name,
> > +
> > +const kvm_hcall_fn_t kvm_hcall_table[__KVM_HOST_HCALL_TABLE_IDX_SIZE] = {
> > +	[0 ... __KVM_HOST_HCALL_TABLE_IDX_SIZE-1] = kvm_hc_ni,
> > +#include <asm/kvm_host_hypercalls.h>
> > +};
> 
> Cunning. At the same time, if you can do this once, you can do it
> twice, and generating the __KVM_HOST_HCALL_TABLE_IDX_* as an enum
> should be pretty easy, and could live in its own include file.

Right, and that again is inspired from the arm64 syscall table (see
arch/arm64/kernel/sys.c). So the first intention was to keep things
consistent. But again, no strong opinion :)

> > diff --git a/arch/arm64/kvm/hyp/hyp-entry.S b/arch/arm64/kvm/hyp/hyp-entry.S
> > index c2a13ab3c471..1a51a0958504 100644
> > --- a/arch/arm64/kvm/hyp/hyp-entry.S
> > +++ b/arch/arm64/kvm/hyp/hyp-entry.S
> > @@ -13,6 +13,7 @@
> >  #include <asm/kvm_arm.h>
> >  #include <asm/kvm_asm.h>
> >  #include <asm/kvm_mmu.h>
> > +#include <asm/kvm_host_hypercalls.h>
> >  #include <asm/mmu.h>
> >  
> >  	.text
> > @@ -21,17 +22,26 @@
> >  .macro do_el2_call
> >  	/*
> >  	 * Shuffle the parameters before calling the function
> > -	 * pointed to in x0. Assumes parameters in x[1,2,3].
> > +	 * pointed to in x0. Assumes parameters in x[1,2,3,4,5,6].
> >  	 */
> >  	str	lr, [sp, #-16]!
> >  	mov	lr, x0
> >  	mov	x0, x1
> >  	mov	x1, x2
> >  	mov	x2, x3
> > +	mov	x3, x4
> > +	mov	x4, x5
> > +	mov	x5, x6
> 
> Has any function changed prototype as part of this patch that they'd
> require this change? It doesn't look like it. I guess this should be
> part of another patch.

Ack, this isn't needed just yet so we should split that out.

> 
> >  	blr	lr
> >  	ldr	lr, [sp], #16
> >  .endm
> >  
> > +/* kern_hyp_va(lm_alias(ksym)) */
> > +.macro ksym_hyp_va ksym, lm_offset
> > +	sub	\ksym, \ksym, \lm_offset
> > +	kern_hyp_va	\ksym
> > +.endm
> > +
> >  el1_sync:				// Guest trapped into EL2
> >  
> >  	mrs	x0, esr_el2
> > @@ -66,10 +76,32 @@ el1_sync:				// Guest trapped into EL2
> >  	br	x5
> >  
> >  1:
> > +	/* Check if the hcall number is valid */
> > +	cmp	x0, #__KVM_HOST_HCALL_BASE
> > +	b.lt	2f
> > +	cmp	x0, #__KVM_HOST_HCALL_END
> > +	b.lt	3f
> > +2:
> > +	mov	x0, -ENOSYS
> > +	eret
> > +
> > +3:
> > +	/* Compute lm_alias() offset in x9 */
> > +	ldr_l	x9, kimage_voffset
> > +	ldr_l	x10, physvirt_offset
> > +	add	x9, x9, x10
> > +
> > +	/* Find hcall function pointer in the table */
> > +	ldr	x10, =kvm_hcall_table
> > +	ksym_hyp_va	x10, x9
> 
> Can't kvm_hcall_table be referenced with adr or adr_l? It'd certainly
> be nice to avoid the extra load for something that is essentially a
> build-time constant.

In fact David already has a nice patch that transforms the whole thing
in a jump table, which is much nicer. I'll let him share the details :)

> Another thing that could be improved is to keep the lm_alias offset
> somewhere, saving one load per entry. Not a huge deal.

Ack.

> > +	sub	x0, x0, #__KVM_HOST_HCALL_BASE
> > +	add	x0, x10, x0, lsl 3
> 
> The usual convention for immediate is to prefix them with #.

Noted, thanks.

> > +	ldr	x0, [x0]
> > +	ksym_hyp_va	x0, x9
> > +
> >  	/*
> >  	 * Perform the EL2 call
> >  	 */
> > -	kern_hyp_va	x0
> >  	do_el2_call
> >  
> >  	eret
> > -- 
> > 2.26.1
> > 
> > 

Thanks for the review!
Quentin

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

  reply	other threads:[~2020-05-07 13:33 UTC|newest]

Thread overview: 99+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-04-30 14:48 [PATCH 00/15] Split off nVHE hyp code David Brazdil
2020-04-30 14:48 ` David Brazdil
2020-04-30 14:48 ` David Brazdil
2020-04-30 14:48 ` [PATCH 01/15] arm64: kvm: Unify users of HVC instruction David Brazdil
2020-04-30 14:48   ` David Brazdil
2020-04-30 14:48   ` David Brazdil
2020-05-07 14:01   ` Marc Zyngier
2020-05-07 14:01     ` Marc Zyngier
2020-05-07 14:01     ` Marc Zyngier
2020-05-07 14:36     ` Quentin Perret
2020-05-07 14:36       ` Quentin Perret
2020-05-07 14:36       ` Quentin Perret
2020-05-13 10:30       ` David Brazdil
2020-05-13 10:30         ` David Brazdil
2020-05-13 10:30         ` David Brazdil
2020-04-30 14:48 ` [PATCH 02/15] arm64: kvm: Formalize host-hyp hypcall ABI David Brazdil
2020-04-30 14:48   ` David Brazdil
2020-04-30 14:48   ` David Brazdil
2020-05-07 13:10   ` Marc Zyngier
2020-05-07 13:10     ` Marc Zyngier
2020-05-07 13:10     ` Marc Zyngier
2020-05-07 13:33     ` Quentin Perret [this message]
2020-05-07 13:33       ` Quentin Perret
2020-05-07 13:33       ` Quentin Perret
2020-05-10 10:16       ` Marc Zyngier
2020-05-10 10:16         ` Marc Zyngier
2020-05-10 10:16         ` Marc Zyngier
2020-05-13 10:48         ` David Brazdil
2020-05-13 10:48           ` David Brazdil
2020-05-13 10:48           ` David Brazdil
2020-04-30 14:48 ` [PATCH 03/15] arm64: kvm: Fix symbol dependency in __hyp_call_panic_nvhe David Brazdil
2020-04-30 14:48   ` David Brazdil
2020-04-30 14:48   ` David Brazdil
2020-05-07 13:22   ` Marc Zyngier
2020-05-07 13:22     ` Marc Zyngier
2020-05-07 13:22     ` Marc Zyngier
2020-05-07 14:36     ` David Brazdil
2020-05-07 14:36       ` David Brazdil
2020-05-07 14:36       ` David Brazdil
2020-05-10 11:14       ` Marc Zyngier
2020-05-10 11:14         ` Marc Zyngier
2020-05-10 11:14         ` Marc Zyngier
2020-04-30 14:48 ` [PATCH 04/15] arm64: kvm: Add build rules for separate nVHE object files David Brazdil
2020-04-30 14:48   ` David Brazdil
2020-04-30 14:48   ` David Brazdil
2020-05-07 13:46   ` Marc Zyngier
2020-05-07 13:46     ` Marc Zyngier
2020-05-07 13:46     ` Marc Zyngier
2020-04-30 14:48 ` [PATCH 05/15] arm64: kvm: Build hyp-entry.S separately for VHE/nVHE David Brazdil
2020-04-30 14:48   ` David Brazdil
2020-04-30 14:48   ` David Brazdil
2020-05-07 15:07   ` Marc Zyngier
2020-05-07 15:07     ` Marc Zyngier
2020-05-07 15:07     ` Marc Zyngier
2020-05-07 15:15     ` Marc Zyngier
2020-05-07 15:15       ` Marc Zyngier
2020-05-07 15:15       ` Marc Zyngier
2020-04-30 14:48 ` [PATCH 06/15] arm64: kvm: Move __smccc_workaround_1_smc to .rodata David Brazdil
2020-04-30 14:48   ` David Brazdil
2020-04-30 14:48   ` David Brazdil
2020-05-11 10:04   ` Marc Zyngier
2020-05-11 10:04     ` Marc Zyngier
2020-05-11 10:04     ` Marc Zyngier
2020-05-11 10:29     ` Will Deacon
2020-05-11 10:29       ` Will Deacon
2020-05-11 10:29       ` Will Deacon
2020-04-30 14:48 ` [PATCH 07/15] arm64: kvm: Split hyp/tlb.c to VHE/nVHE David Brazdil
2020-04-30 14:48   ` David Brazdil
2020-04-30 14:48   ` David Brazdil
2020-04-30 14:48 ` [PATCH 08/15] arm64: kvm: Split hyp/switch.c " David Brazdil
2020-04-30 14:48   ` David Brazdil
2020-04-30 14:48   ` David Brazdil
2020-04-30 14:48 ` [PATCH 09/15] arm64: kvm: Split hyp/debug-sr.c " David Brazdil
2020-04-30 14:48   ` David Brazdil
2020-04-30 14:48   ` David Brazdil
2020-04-30 14:48 ` [PATCH 10/15] arm64: kvm: Split hyp/sysreg-sr.c " David Brazdil
2020-04-30 14:48   ` David Brazdil
2020-04-30 14:48   ` David Brazdil
2020-04-30 14:48 ` [PATCH 11/15] arm64: kvm: Split hyp/timer-sr.c " David Brazdil
2020-04-30 14:48   ` David Brazdil
2020-04-30 14:48   ` David Brazdil
2020-04-30 14:48 ` [PATCH 12/15] arm64: kvm: Compile remaining hyp/ files for both VHE/nVHE David Brazdil
2020-04-30 14:48   ` David Brazdil
2020-04-30 14:48   ` David Brazdil
2020-04-30 14:48 ` [PATCH 13/15] arm64: kvm: Add comments around __hyp_text_ symbol aliases David Brazdil
2020-04-30 14:48   ` David Brazdil
2020-04-30 14:48   ` David Brazdil
2020-04-30 14:48 ` [PATCH 14/15] arm64: kvm: Remove __hyp_text macro, use build rules instead David Brazdil
2020-04-30 14:48   ` David Brazdil
2020-04-30 14:48   ` David Brazdil
2020-04-30 14:48 ` [PATCH 15/15] arm64: kvm: Lift instrumentation restrictions on VHE David Brazdil
2020-04-30 14:48   ` David Brazdil
2020-04-30 14:48   ` David Brazdil
2020-04-30 17:53 ` [PATCH 00/15] Split off nVHE hyp code Marc Zyngier
2020-04-30 17:53   ` Marc Zyngier
2020-04-30 17:53   ` Marc Zyngier
2020-04-30 18:57   ` David Brazdil
2020-04-30 18:57     ` David Brazdil
2020-04-30 18:57     ` David Brazdil

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200507133320.GA16899@google.com \
    --to=qperret@google.com \
    --cc=catalin.marinas@arm.com \
    --cc=dbrazdil@google.com \
    --cc=james.morse@arm.com \
    --cc=julien.thierry.kdev@gmail.com \
    --cc=kvmarm@lists.cs.columbia.edu \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=maz@kernel.org \
    --cc=suzuki.poulose@arm.com \
    --cc=will@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.