[v12,26/31] LoongArch: KVM: Implement kvm exception vector

Message ID 20230530015223.147755-27-zhaotianrui@loongson.cn
State New
Headers
Series Add KVM LoongArch support |

Commit Message

zhaotianrui May 30, 2023, 1:52 a.m. UTC
  Implement kvm exception vector, using _kvm_fault_tables array to save
the handle function pointer and it is used when vcpu handle exit.

Signed-off-by: Tianrui Zhao <zhaotianrui@loongson.cn>
---
 arch/loongarch/kvm/exit.c | 48 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)
  

Comments

maobibo June 6, 2023, 1:43 a.m. UTC | #1
Reviewed-by: Bibo, Mao <maobibo@loongson.cn>

在 2023/5/30 09:52, Tianrui Zhao 写道:
> Implement kvm exception vector, using _kvm_fault_tables array to save
> the handle function pointer and it is used when vcpu handle exit.
> 
> Signed-off-by: Tianrui Zhao <zhaotianrui@loongson.cn>
> ---
>  arch/loongarch/kvm/exit.c | 48 +++++++++++++++++++++++++++++++++++++++
>  1 file changed, 48 insertions(+)
> 
> diff --git a/arch/loongarch/kvm/exit.c b/arch/loongarch/kvm/exit.c
> index 10f9922a7e76..625045fc95c8 100644
> --- a/arch/loongarch/kvm/exit.c
> +++ b/arch/loongarch/kvm/exit.c
> @@ -657,3 +657,51 @@ static int _kvm_handle_fpu_disabled(struct kvm_vcpu *vcpu)
>  	kvm_own_fpu(vcpu);
>  	return RESUME_GUEST;
>  }
> +
> +/*
> + * Loongarch KVM callback handling for not implemented guest exiting
> + */
> +static int _kvm_fault_ni(struct kvm_vcpu *vcpu)
> +{
> +	unsigned long estat, badv;
> +	unsigned int exccode, inst;
> +
> +	/*
> +	 *  Fetch the instruction.
> +	 */
> +	badv = vcpu->arch.badv;
> +	estat = vcpu->arch.host_estat;
> +	exccode = (estat & CSR_ESTAT_EXC) >> CSR_ESTAT_EXC_SHIFT;
> +	inst = vcpu->arch.badi;
> +	kvm_err("Exccode: %d PC=%#lx inst=0x%08x BadVaddr=%#lx estat=%#lx\n",
> +			exccode, vcpu->arch.pc, inst, badv, read_gcsr_estat());
> +	kvm_arch_vcpu_dump_regs(vcpu);
> +	vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
> +
> +	return RESUME_HOST;
> +}
> +
> +static exit_handle_fn _kvm_fault_tables[EXCCODE_INT_START] = {
> +	[EXCCODE_TLBL]		= _kvm_handle_read_fault,
> +	[EXCCODE_TLBI]		= _kvm_handle_read_fault,
> +	[EXCCODE_TLBNR]		= _kvm_handle_read_fault,
> +	[EXCCODE_TLBNX]		= _kvm_handle_read_fault,
> +	[EXCCODE_TLBS]		= _kvm_handle_write_fault,
> +	[EXCCODE_TLBM]		= _kvm_handle_write_fault,
> +	[EXCCODE_FPDIS]		= _kvm_handle_fpu_disabled,
> +	[EXCCODE_GSPR]		= _kvm_handle_gspr,
> +};
> +
> +int _kvm_handle_fault(struct kvm_vcpu *vcpu, int fault)
> +{
> +	return _kvm_fault_tables[fault](vcpu);
> +}
> +
> +void _kvm_init_fault(void)
> +{
> +	int i;
> +
> +	for (i = 0; i < EXCCODE_INT_START; i++)
> +		if (!_kvm_fault_tables[i])
> +			_kvm_fault_tables[i] = _kvm_fault_ni;
> +}
  
Youling Tang June 6, 2023, 7 a.m. UTC | #2
On 05/30/2023 09:52 AM, Tianrui Zhao wrote:
> Implement kvm exception vector, using _kvm_fault_tables array to save
> the handle function pointer and it is used when vcpu handle exit.
>
> Signed-off-by: Tianrui Zhao <zhaotianrui@loongson.cn>
> ---
>  arch/loongarch/kvm/exit.c | 48 +++++++++++++++++++++++++++++++++++++++
>  1 file changed, 48 insertions(+)
>
> diff --git a/arch/loongarch/kvm/exit.c b/arch/loongarch/kvm/exit.c
> index 10f9922a7e76..625045fc95c8 100644
> --- a/arch/loongarch/kvm/exit.c
> +++ b/arch/loongarch/kvm/exit.c
> @@ -657,3 +657,51 @@ static int _kvm_handle_fpu_disabled(struct kvm_vcpu *vcpu)
>  	kvm_own_fpu(vcpu);
>  	return RESUME_GUEST;
>  }
> +
> +/*
> + * Loongarch KVM callback handling for not implemented guest exiting
> + */
> +static int _kvm_fault_ni(struct kvm_vcpu *vcpu)
> +{
> +	unsigned long estat, badv;
> +	unsigned int exccode, inst;
> +
> +	/*
> +	 *  Fetch the instruction.
> +	 */
> +	badv = vcpu->arch.badv;
> +	estat = vcpu->arch.host_estat;
> +	exccode = (estat & CSR_ESTAT_EXC) >> CSR_ESTAT_EXC_SHIFT;
> +	inst = vcpu->arch.badi;
> +	kvm_err("Exccode: %d PC=%#lx inst=0x%08x BadVaddr=%#lx estat=%#lx\n",
> +			exccode, vcpu->arch.pc, inst, badv, read_gcsr_estat());
> +	kvm_arch_vcpu_dump_regs(vcpu);
> +	vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
> +
> +	return RESUME_HOST;
> +}
> +
> +static exit_handle_fn _kvm_fault_tables[EXCCODE_INT_START] = {
> +	[EXCCODE_TLBL]		= _kvm_handle_read_fault,
> +	[EXCCODE_TLBI]		= _kvm_handle_read_fault,
> +	[EXCCODE_TLBNR]		= _kvm_handle_read_fault,
> +	[EXCCODE_TLBNX]		= _kvm_handle_read_fault,
> +	[EXCCODE_TLBS]		= _kvm_handle_write_fault,
> +	[EXCCODE_TLBM]		= _kvm_handle_write_fault,
> +	[EXCCODE_FPDIS]		= _kvm_handle_fpu_disabled,
> +	[EXCCODE_GSPR]		= _kvm_handle_gspr,
> +};
It can be modified as follows and remove _kvm_init_fault().

static exit_handle_fn _kvm_fault_tables[EXCCODE_INT_START] = {
	[0 ... EXCCODE_INT_START - 1]	= _kvm_fault_ni,

	[EXCCODE_TLBL]			= _kvm_handle_read_fault,
	[EXCCODE_TLBI]			= _kvm_handle_read_fault,
	[EXCCODE_TLBNR]			= _kvm_handle_read_fault,
	[EXCCODE_TLBNX]			= _kvm_handle_read_fault,
	[EXCCODE_TLBS]			= _kvm_handle_write_fault,
	[EXCCODE_TLBM]			= _kvm_handle_write_fault,
	[EXCCODE_FPDIS]			= _kvm_handle_fpu_disabled,
	[EXCCODE_GSPR]			= _kvm_handle_gspr,
};

Thanks,
Youling

> +
> +int _kvm_handle_fault(struct kvm_vcpu *vcpu, int fault)
> +{
> +	return _kvm_fault_tables[fault](vcpu);
> +}
> +
> +void _kvm_init_fault(void)
> +{
> +	int i;
> +
> +	for (i = 0; i < EXCCODE_INT_START; i++)
> +		if (!_kvm_fault_tables[i])
> +			_kvm_fault_tables[i] = _kvm_fault_ni;
> +}
>
  
zhaotianrui June 6, 2023, 9:16 a.m. UTC | #3
在 2023年06月06日 15:00, Youling Tang 写道:
>
>
> On 05/30/2023 09:52 AM, Tianrui Zhao wrote:
>> Implement kvm exception vector, using _kvm_fault_tables array to save
>> the handle function pointer and it is used when vcpu handle exit.
>>
>> Signed-off-by: Tianrui Zhao <zhaotianrui@loongson.cn>
>> ---
>>  arch/loongarch/kvm/exit.c | 48 +++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 48 insertions(+)
>>
>> diff --git a/arch/loongarch/kvm/exit.c b/arch/loongarch/kvm/exit.c
>> index 10f9922a7e76..625045fc95c8 100644
>> --- a/arch/loongarch/kvm/exit.c
>> +++ b/arch/loongarch/kvm/exit.c
>> @@ -657,3 +657,51 @@ static int _kvm_handle_fpu_disabled(struct 
>> kvm_vcpu *vcpu)
>>      kvm_own_fpu(vcpu);
>>      return RESUME_GUEST;
>>  }
>> +
>> +/*
>> + * Loongarch KVM callback handling for not implemented guest exiting
>> + */
>> +static int _kvm_fault_ni(struct kvm_vcpu *vcpu)
>> +{
>> +    unsigned long estat, badv;
>> +    unsigned int exccode, inst;
>> +
>> +    /*
>> +     *  Fetch the instruction.
>> +     */
>> +    badv = vcpu->arch.badv;
>> +    estat = vcpu->arch.host_estat;
>> +    exccode = (estat & CSR_ESTAT_EXC) >> CSR_ESTAT_EXC_SHIFT;
>> +    inst = vcpu->arch.badi;
>> +    kvm_err("Exccode: %d PC=%#lx inst=0x%08x BadVaddr=%#lx 
>> estat=%#lx\n",
>> +            exccode, vcpu->arch.pc, inst, badv, read_gcsr_estat());
>> +    kvm_arch_vcpu_dump_regs(vcpu);
>> +    vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
>> +
>> +    return RESUME_HOST;
>> +}
>> +
>> +static exit_handle_fn _kvm_fault_tables[EXCCODE_INT_START] = {
>> +    [EXCCODE_TLBL]        = _kvm_handle_read_fault,
>> +    [EXCCODE_TLBI]        = _kvm_handle_read_fault,
>> +    [EXCCODE_TLBNR]        = _kvm_handle_read_fault,
>> +    [EXCCODE_TLBNX]        = _kvm_handle_read_fault,
>> +    [EXCCODE_TLBS]        = _kvm_handle_write_fault,
>> +    [EXCCODE_TLBM]        = _kvm_handle_write_fault,
>> +    [EXCCODE_FPDIS]        = _kvm_handle_fpu_disabled,
>> +    [EXCCODE_GSPR]        = _kvm_handle_gspr,
>> +};
> It can be modified as follows and remove _kvm_init_fault().
>
> static exit_handle_fn _kvm_fault_tables[EXCCODE_INT_START] = {
>     [0 ... EXCCODE_INT_START - 1]    = _kvm_fault_ni,
>
>     [EXCCODE_TLBL]            = _kvm_handle_read_fault,
>     [EXCCODE_TLBI]            = _kvm_handle_read_fault,
>     [EXCCODE_TLBNR]            = _kvm_handle_read_fault,
>     [EXCCODE_TLBNX]            = _kvm_handle_read_fault,
>     [EXCCODE_TLBS]            = _kvm_handle_write_fault,
>     [EXCCODE_TLBM]            = _kvm_handle_write_fault,
>     [EXCCODE_FPDIS]            = _kvm_handle_fpu_disabled,
>     [EXCCODE_GSPR]            = _kvm_handle_gspr,
> };
>
> Thanks,
> Youling
Thanks, this method can simplify the code, I will fix it.

Thanks
Tianrui Zhao
>
>> +
>> +int _kvm_handle_fault(struct kvm_vcpu *vcpu, int fault)
>> +{
>> +    return _kvm_fault_tables[fault](vcpu);
>> +}
>> +
>> +void _kvm_init_fault(void)
>> +{
>> +    int i;
>> +
>> +    for (i = 0; i < EXCCODE_INT_START; i++)
>> +        if (!_kvm_fault_tables[i])
>> +            _kvm_fault_tables[i] = _kvm_fault_ni;
>> +}
>>
  
zhaotianrui June 8, 2023, 11:44 a.m. UTC | #4
> -----原始邮件-----
> 发件人: "Youling Tang" <tangyouling@loongson.cn>
> 发送时间:2023-06-06 15:00:11 (星期二)
> 收件人: "Tianrui Zhao" <zhaotianrui@loongson.cn>
> 抄送: linux-kernel@vger.kernel.org, kvm@vger.kernel.org, "Paolo Bonzini" <pbonzini@redhat.com>, "Huacai Chen" <chenhuacai@kernel.org>, "WANG Xuerui" <kernel@xen0n.name>, "Greg Kroah-Hartman" <gregkh@linuxfoundation.org>, loongarch@lists.linux.dev, "Jens Axboe" <axboe@kernel.dk>, "Mark Brown" <broonie@kernel.org>, "Alex Deucher" <alexander.deucher@amd.com>, "Oliver Upton" <oliver.upton@linux.dev>, maobibo@loongson.cn, "Xi Ruoyao" <xry111@xry111.site>
> 主题: Re: [PATCH v12 26/31] LoongArch: KVM: Implement kvm exception vector
> 
> 
> 
> On 05/30/2023 09:52 AM, Tianrui Zhao wrote:
> > Implement kvm exception vector, using _kvm_fault_tables array to save
> > the handle function pointer and it is used when vcpu handle exit.
> >
> > Signed-off-by: Tianrui Zhao <zhaotianrui@loongson.cn>
> > ---
> >  arch/loongarch/kvm/exit.c | 48 +++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 48 insertions(+)
> >
> > diff --git a/arch/loongarch/kvm/exit.c b/arch/loongarch/kvm/exit.c
> > index 10f9922a7e76..625045fc95c8 100644
> > --- a/arch/loongarch/kvm/exit.c
> > +++ b/arch/loongarch/kvm/exit.c
> > @@ -657,3 +657,51 @@ static int _kvm_handle_fpu_disabled(struct kvm_vcpu *vcpu)
> >  	kvm_own_fpu(vcpu);
> >  	return RESUME_GUEST;
> >  }
> > +
> > +/*
> > + * Loongarch KVM callback handling for not implemented guest exiting
> > + */
> > +static int _kvm_fault_ni(struct kvm_vcpu *vcpu)
> > +{
> > +	unsigned long estat, badv;
> > +	unsigned int exccode, inst;
> > +
> > +	/*
> > +	 *  Fetch the instruction.
> > +	 */
> > +	badv = vcpu->arch.badv;
> > +	estat = vcpu->arch.host_estat;
> > +	exccode = (estat & CSR_ESTAT_EXC) >> CSR_ESTAT_EXC_SHIFT;
> > +	inst = vcpu->arch.badi;
> > +	kvm_err("Exccode: %d PC=%#lx inst=0x%08x BadVaddr=%#lx estat=%#lx\n",
> > +			exccode, vcpu->arch.pc, inst, badv, read_gcsr_estat());
> > +	kvm_arch_vcpu_dump_regs(vcpu);
> > +	vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
> > +
> > +	return RESUME_HOST;
> > +}
> > +
> > +static exit_handle_fn _kvm_fault_tables[EXCCODE_INT_START] = {
> > +	[EXCCODE_TLBL]		= _kvm_handle_read_fault,
> > +	[EXCCODE_TLBI]		= _kvm_handle_read_fault,
> > +	[EXCCODE_TLBNR]		= _kvm_handle_read_fault,
> > +	[EXCCODE_TLBNX]		= _kvm_handle_read_fault,
> > +	[EXCCODE_TLBS]		= _kvm_handle_write_fault,
> > +	[EXCCODE_TLBM]		= _kvm_handle_write_fault,
> > +	[EXCCODE_FPDIS]		= _kvm_handle_fpu_disabled,
> > +	[EXCCODE_GSPR]		= _kvm_handle_gspr,
> > +};
> It can be modified as follows and remove _kvm_init_fault().
> 
> static exit_handle_fn _kvm_fault_tables[EXCCODE_INT_START] = {
> 	[0 ... EXCCODE_INT_START - 1]	= _kvm_fault_ni,
> 
> 	[EXCCODE_TLBL]			= _kvm_handle_read_fault,
> 	[EXCCODE_TLBI]			= _kvm_handle_read_fault,
> 	[EXCCODE_TLBNR]			= _kvm_handle_read_fault,
> 	[EXCCODE_TLBNX]			= _kvm_handle_read_fault,
> 	[EXCCODE_TLBS]			= _kvm_handle_write_fault,
> 	[EXCCODE_TLBM]			= _kvm_handle_write_fault,
> 	[EXCCODE_FPDIS]			= _kvm_handle_fpu_disabled,
> 	[EXCCODE_GSPR]			= _kvm_handle_gspr,
> };
> 
> Thanks,
> Youling
Hi Youling,
When I compile this code with W=1, there is a warning: initialized field overwritten [-Woverride-init], so considering this problem I think we have to keep the previous _kvm_init_fault, what do you think of it?

Thanks
Tianrui Zhao
> 
> > +
> > +int _kvm_handle_fault(struct kvm_vcpu *vcpu, int fault)
> > +{
> > +	return _kvm_fault_tables[fault](vcpu);
> > +}
> > +
> > +void _kvm_init_fault(void)
> > +{
> > +	int i;
> > +
> > +	for (i = 0; i < EXCCODE_INT_START; i++)
> > +		if (!_kvm_fault_tables[i])
> > +			_kvm_fault_tables[i] = _kvm_fault_ni;
> > +}
> >


本邮件及其附件含有龙芯中科的商业秘密信息,仅限于发送给上面地址中列出的个人或群组。禁止任何其他人以任何形式使用(包括但不限于全部或部分地泄露、复制或散发)本邮件及其附件中的信息。如果您错收本邮件,请您立即电话或邮件通知发件人并删除本邮件。 
This email and its attachments contain confidential information from Loongson Technology , which is intended only for the person or entity whose address is listed above. Any use of the information contained herein in any way (including, but not limited to, total or partial disclosure, reproduction or dissemination) by persons other than the intended recipient(s) is prohibited. If you receive this email in error, please notify the sender by phone or email immediately and delete it.
  

Patch

diff --git a/arch/loongarch/kvm/exit.c b/arch/loongarch/kvm/exit.c
index 10f9922a7e76..625045fc95c8 100644
--- a/arch/loongarch/kvm/exit.c
+++ b/arch/loongarch/kvm/exit.c
@@ -657,3 +657,51 @@  static int _kvm_handle_fpu_disabled(struct kvm_vcpu *vcpu)
 	kvm_own_fpu(vcpu);
 	return RESUME_GUEST;
 }
+
+/*
+ * Loongarch KVM callback handling for not implemented guest exiting
+ */
+static int _kvm_fault_ni(struct kvm_vcpu *vcpu)
+{
+	unsigned long estat, badv;
+	unsigned int exccode, inst;
+
+	/*
+	 *  Fetch the instruction.
+	 */
+	badv = vcpu->arch.badv;
+	estat = vcpu->arch.host_estat;
+	exccode = (estat & CSR_ESTAT_EXC) >> CSR_ESTAT_EXC_SHIFT;
+	inst = vcpu->arch.badi;
+	kvm_err("Exccode: %d PC=%#lx inst=0x%08x BadVaddr=%#lx estat=%#lx\n",
+			exccode, vcpu->arch.pc, inst, badv, read_gcsr_estat());
+	kvm_arch_vcpu_dump_regs(vcpu);
+	vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+
+	return RESUME_HOST;
+}
+
+static exit_handle_fn _kvm_fault_tables[EXCCODE_INT_START] = {
+	[EXCCODE_TLBL]		= _kvm_handle_read_fault,
+	[EXCCODE_TLBI]		= _kvm_handle_read_fault,
+	[EXCCODE_TLBNR]		= _kvm_handle_read_fault,
+	[EXCCODE_TLBNX]		= _kvm_handle_read_fault,
+	[EXCCODE_TLBS]		= _kvm_handle_write_fault,
+	[EXCCODE_TLBM]		= _kvm_handle_write_fault,
+	[EXCCODE_FPDIS]		= _kvm_handle_fpu_disabled,
+	[EXCCODE_GSPR]		= _kvm_handle_gspr,
+};
+
+int _kvm_handle_fault(struct kvm_vcpu *vcpu, int fault)
+{
+	return _kvm_fault_tables[fault](vcpu);
+}
+
+void _kvm_init_fault(void)
+{
+	int i;
+
+	for (i = 0; i < EXCCODE_INT_START; i++)
+		if (!_kvm_fault_tables[i])
+			_kvm_fault_tables[i] = _kvm_fault_ni;
+}