Received: by 2002:a05:6358:3188:b0:123:57c1:9b43 with SMTP id q8csp18920561rwd; Wed, 28 Jun 2023 02:30:27 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ6fxbxHzlDF7vbW2PYF6OYiG4frGYRGh14nGRyLtMfYS6+1FyNZC5nPGF6hb9q15TjpeMKQ X-Received: by 2002:aa7:cf85:0:b0:51d:b244:2ffe with SMTP id z5-20020aa7cf85000000b0051db2442ffemr671328edx.21.1687944627158; Wed, 28 Jun 2023 02:30:27 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1687944627; cv=none; d=google.com; s=arc-20160816; b=jSfENT63V8+3wir9NrF5FVJD+6Yq8HRSOrTq8/s9tl6Z/F7lxPn9862lVshdmoo1nf U7vyqB7J+nRVNQNmUFNYMHhVkdM4GXpuEdErcXjh597bJ2TCBsBNVDUKC3QYT3bd3f7n emwYr/DuuTw6JGWH65+Yk95Mxa7ORgvxXImDeBWOL/emdBBVXToJCjSy8JbMe+azL8d8 XZVfA7trYr4RnZyGVhrdutNaqSTb5qsQC/3OXtcMdC80ScYIvgdcVg3cJbFIRXGx8ZK+ TRYEEAAwuoryYHY8WmvSYcWuCjhuCLcdGzmESExfF3Zr2+ea+G6K9Hy4a2+6vYDmXip2 y/Nw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-language:content-transfer-encoding :in-reply-to:mime-version:user-agent:date:message-id:from:references :cc:to:subject; bh=6ZpavS/0vdw/Zq6bZmoN/xymWAPqJdHsnhOzlyhpVbE=; fh=QDN1BWDowYlX0uuVUukcg/68FQOeZKWoCuaVUacv8jQ=; b=CQ7R4BjXnKBpMS63CWqAhhUPe+InZAyKCa9fsVG1Qnnkn8I+CirgRhSib982ySc0BZ 3hfjZaGgSkCbQcheiMOo14VJEaxVEIxoX6HFu9tx+RKZPJSZw6qSP1Z2DEjsSU/rBcLW 50TLt+DrKgED1naobxJnzxV2mTvgrYFosWEgnUqGAXXDcym39kWcutkTaxFgzciEx1ij iB9bYTv/WE8BtWTf3qTYQmxlKGC4QO5PWrM/7z+mUD/16yyxQolVchngAWfmquwHBXSp ESaWW0Txp/xPq+Or2HLejd6xxlrdCxm3BIxaoaQiYVM5dCvPkhNY1DYEyOABjK4EdzQR tzOw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id k12-20020aa7c38c000000b0051a5acd425esi4921325edq.403.2023.06.28.02.30.02; Wed, 28 Jun 2023 02:30:27 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235605AbjF1Ih0 (ORCPT + 99 others); Wed, 28 Jun 2023 04:37:26 -0400 Received: from mail.loongson.cn ([114.242.206.163]:49982 "EHLO mail.loongson.cn" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234924AbjF1IeP (ORCPT ); Wed, 28 Jun 2023 04:34:15 -0400 Received: from loongson.cn (unknown [10.40.46.158]) by gateway (Coremail) with SMTP id _____8AxiMWF8JtkEWgDAA--.5445S3; Wed, 28 Jun 2023 16:34:13 +0800 (CST) Received: from [192.168.124.126] (unknown [10.40.46.158]) by localhost.localdomain (Coremail) with SMTP id AQAAf8DxfSOC8Jtkzv0NAA--.4329S3; Wed, 28 Jun 2023 16:34:11 +0800 (CST) Subject: Re: [PATCH v15 27/30] LoongArch: KVM: Implement vcpu world switch To: Jinyang He , linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: Paolo Bonzini , Huacai Chen , WANG Xuerui , Greg Kroah-Hartman , loongarch@lists.linux.dev, Jens Axboe , Mark Brown , Alex Deucher , Oliver Upton , maobibo@loongson.cn, Xi Ruoyao , tangyouling@loongson.cn References: <20230626084752.1138621-1-zhaotianrui@loongson.cn> <20230626084752.1138621-28-zhaotianrui@loongson.cn> From: zhaotianrui Message-ID: <7017277c-3721-b417-5215-491efae7c8a9@loongson.cn> Date: Wed, 28 Jun 2023 16:34:10 +0800 User-Agent: Mozilla/5.0 (X11; Linux loongarch64; rv:68.0) Gecko/20100101 Thunderbird/68.7.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit Content-Language: en-US X-CM-TRANSID: AQAAf8DxfSOC8Jtkzv0NAA--.4329S3 X-CM-SenderInfo: p2kd03xldq233l6o00pqjv00gofq/ X-Coremail-Antispam: 1Uk129KBj9fXoW3Cw15Gw4DAw1xJr4kJFy5trc_yoW8ArWfJo WjgF10q343JrWjgr48Gw45trW3X3WUGrnFqryUGryxJr1FvF1rJ3y7Kay2gayUJr18Gr1U tF9xJry0kFyrAr15l-sFpf9Il3svdjkaLaAFLSUrUUUUeb8apTn2vfkv8UJUUUU8wcxFpf 9Il3svdxBIdaVrn0xqx4xG64xvF2IEw4CE5I8CrVC2j2Jv73VFW2AGmfu7bjvjm3AaLaJ3 UjIYCTnIWjp_UUUO07kC6x804xWl14x267AKxVWUJVW8JwAFc2x0x2IEx4CE42xK8VAvwI 8IcIk0rVWrJVCq3wAFIxvE14AKwVWUXVWUAwA2ocxC64kIII0Yj41l84x0c7CEw4AK67xG Y2AK021l84ACjcxK6xIIjxv20xvE14v26r1I6r4UM28EF7xvwVC0I7IYx2IY6xkF7I0E14 v26r1j6r4UM28EF7xvwVC2z280aVAFwI0_Gr1j6F4UJwA2z4x0Y4vEx4A2jsIEc7CjxVAF wI0_Gr1j6F4UJwAaw2AFwI0_JF0_Jw1le2I262IYc4CY6c8Ij28IcVAaY2xG8wAqjxCEc2 xF0cIa020Ex4CE44I27wAqx4xG64xvF2IEw4CE5I8CrVC2j2WlYx0E2Ix0cI8IcVAFwI0_ JF0_Jw1lYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE7xkEbVWUJVW8JwACjcxG0xvEwI xGrwCYjI0SjxkI62AI1cAE67vIY487MxkF7I0En4kS14v26r126r1DMxAIw28IcxkI7VAK I48JMxC20s026xCaFVCjc4AY6r1j6r4UMxCIbckI1I0E14v26r126r1DMI8I3I0E5I8CrV AFwI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVWUtVW8ZwCI c40Y0x0EwIxGrwCI42IY6xIIjxv20xvE14v26r1I6r4UMIIF0xvE2Ix0cI8IcVCY1x0267 AKxVWUJVW8JwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_Jr0_ Gr1lIxAIcVC2z280aVCY1x0267AKxVWUJVW8JbIYCTnIWIevJa73UjIFyTuYvjxUcbAwUU UUU Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 在 2023/6/28 上午11:42, Jinyang He 写道: > On 2023-06-26 16:47, Tianrui Zhao wrote: > >> Implement LoongArch vcpu world switch, including vcpu enter guest and >> vcpu exit from guest, both operations need to save or restore the host >> and guest registers. >> >> Reviewed-by: Bibo Mao >> Signed-off-by: Tianrui Zhao >> --- >>   arch/loongarch/kernel/asm-offsets.c |  32 +++ >>   arch/loongarch/kvm/switch.S         | 299 ++++++++++++++++++++++++++++ >>   2 files changed, 331 insertions(+) >>   create mode 100644 arch/loongarch/kvm/switch.S >> >> diff --git a/arch/loongarch/kernel/asm-offsets.c >> b/arch/loongarch/kernel/asm-offsets.c >> index 4bdb203fc66e..cb6c5a5afea9 100644 >> --- a/arch/loongarch/kernel/asm-offsets.c >> +++ b/arch/loongarch/kernel/asm-offsets.c >> @@ -9,6 +9,7 @@ >>   #include >>   #include >>   #include >> +#include >>   #include >>   #include >>   #include >> @@ -272,3 +273,34 @@ void output_pbe_defines(void) >>       BLANK(); >>   } >>   #endif >> + >> +static void __used output_kvm_defines(void) >> +{ >> +    COMMENT(" KVM/LOONGARCH Specific offsets. "); >> + >> +    OFFSET(VCPU_FCSR0, kvm_vcpu_arch, fpu.fcsr); >> +    OFFSET(VCPU_FCC, kvm_vcpu_arch, fpu.fcc); >> +    BLANK(); >> + >> +    OFFSET(KVM_VCPU_ARCH, kvm_vcpu, arch); >> +    OFFSET(KVM_VCPU_KVM, kvm_vcpu, kvm); >> +    OFFSET(KVM_VCPU_RUN, kvm_vcpu, run); >> +    BLANK(); >> + >> +    OFFSET(KVM_ARCH_HSP, kvm_vcpu_arch, host_sp); >> +    OFFSET(KVM_ARCH_HTP, kvm_vcpu_arch, host_tp); >> +    OFFSET(KVM_ARCH_HANDLE_EXIT, kvm_vcpu_arch, handle_exit); >> +    OFFSET(KVM_ARCH_HPGD, kvm_vcpu_arch, host_pgd); >> +    OFFSET(KVM_ARCH_GEENTRY, kvm_vcpu_arch, guest_eentry); >> +    OFFSET(KVM_ARCH_GPC, kvm_vcpu_arch, pc); >> +    OFFSET(KVM_ARCH_GGPR, kvm_vcpu_arch, gprs); >> +    OFFSET(KVM_ARCH_HESTAT, kvm_vcpu_arch, host_estat); >> +    OFFSET(KVM_ARCH_HBADV, kvm_vcpu_arch, badv); >> +    OFFSET(KVM_ARCH_HBADI, kvm_vcpu_arch, badi); >> +    OFFSET(KVM_ARCH_HECFG, kvm_vcpu_arch, host_ecfg); >> +    OFFSET(KVM_ARCH_HEENTRY, kvm_vcpu_arch, host_eentry); >> +    OFFSET(KVM_ARCH_HPERCPU, kvm_vcpu_arch, host_percpu); >> + >> +    OFFSET(KVM_GPGD, kvm, arch.gpa_mm.pgd); >> +    BLANK(); >> +} >> diff --git a/arch/loongarch/kvm/switch.S b/arch/loongarch/kvm/switch.S >> new file mode 100644 >> index 000000000000..7e55976c6fec >> --- /dev/null >> +++ b/arch/loongarch/kvm/switch.S >> @@ -0,0 +1,299 @@ >> +/* SPDX-License-Identifier: GPL-2.0 */ >> +/* >> + * Copyright (C) 2020-2023 Loongson Technology Corporation Limited >> + */ >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +#define PT_GPR_OFFSET(x)    (PT_R0 + 8*x) >> +    .text > > The .text is redundant, you also marked it later. Thanks, I will remove this .text > > >> + >> +.macro kvm_save_host_gpr base >> +    .irp n,1,2,3,22,23,24,25,26,27,28,29,30,31 >> +    st.d    $r\n, \base, PT_GPR_OFFSET(\n) >> +    .endr >> +.endm >> + >> +.macro kvm_restore_host_gpr base >> +    .irp n,1,2,3,22,23,24,25,26,27,28,29,30,31 >> +    ld.d    $r\n, \base, PT_GPR_OFFSET(\n) >> +    .endr >> +.endm >> + >> +/* >> + * prepare switch to guest, save host reg and restore guest reg. >> + * a2: kvm_vcpu_arch, don't touch it until 'ertn' >> + * t0, t1: temp register >> + */ >> +.macro kvm_switch_to_guest >> +    /* set host excfg.VS=0, all exceptions share one exception entry */ >> +    csrrd        t0, LOONGARCH_CSR_ECFG >> +    bstrins.w    t0, zero, CSR_ECFG_VS_SHIFT_END, CSR_ECFG_VS_SHIFT >> +    csrwr        t0, LOONGARCH_CSR_ECFG >> + >> +    /* Load up the new EENTRY */ >> +    ld.d    t0, a2, KVM_ARCH_GEENTRY >> +    csrwr    t0, LOONGARCH_CSR_EENTRY >> + >> +    /* Set Guest ERA */ >> +    ld.d    t0, a2, KVM_ARCH_GPC >> +    csrwr    t0, LOONGARCH_CSR_ERA >> + >> +    /* Save host PGDL */ >> +    csrrd    t0, LOONGARCH_CSR_PGDL >> +    st.d    t0, a2, KVM_ARCH_HPGD >> + >> +    /* Switch to kvm */ >> +    ld.d    t1, a2, KVM_VCPU_KVM - KVM_VCPU_ARCH >> + >> +    /* Load guest PGDL */ >> +    lu12i.w t0, KVM_GPGD >> +    srli.w  t0, t0, 12 > > I think the "lu12i.w+srli.w" can be replaced by "li.w t0, KVM_GPGD" . Thanks, I will use "li.w t0, KVM_GPGD" to simplify the two instructions. > > >> +    ldx.d   t0, t1, t0 >> +    csrwr    t0, LOONGARCH_CSR_PGDL >> + >> +    /* Mix GID and RID */ >> +    csrrd        t1, LOONGARCH_CSR_GSTAT >> +    bstrpick.w    t1, t1, CSR_GSTAT_GID_SHIFT_END, CSR_GSTAT_GID_SHIFT >> +    csrrd        t0, LOONGARCH_CSR_GTLBC >> +    bstrins.w    t0, t1, CSR_GTLBC_TGID_SHIFT_END, CSR_GTLBC_TGID_SHIFT >> +    csrwr        t0, LOONGARCH_CSR_GTLBC >> + >> +    /* >> +     * Switch to guest: >> +     *  GSTAT.PGM = 1, ERRCTL.ISERR = 0, TLBRPRMD.ISTLBR = 0 >> +     *  ertn >> +     */ >> + >> +    /* >> +     * Enable intr in root mode with future ertn so that host interrupt >> +     * can be responsed during VM runs >> +     * guest crmd comes from separate gcsr_CRMD register >> +     */ >> +    ori    t0, zero, CSR_PRMD_PIE > li.w t0, CSR_PRMD_PIE Thanks for your advice, and I think it need not to replace it with "li.w" there, as it has the same meaning with "ori" instruction, and "ori" instruction is simple and clear enough. The same as the following "move" instructions. What do you think of it. >> +    csrxchg    t0, t0, LOONGARCH_CSR_PRMD >> + >> +    /* Set PVM bit to setup ertn to guest context */ >> +    ori    t0, zero, CSR_GSTAT_PVM > li.w t0, ... >> +    csrxchg    t0, t0, LOONGARCH_CSR_GSTAT >> + >> +    /* Load Guest gprs */ >> +    ld.d    ra,    a2,    (KVM_ARCH_GGPR + 8 * REG_RA) >> +    ld.d    tp,    a2,    (KVM_ARCH_GGPR + 8 * REG_TP) >> +    ld.d    sp,    a2,    (KVM_ARCH_GGPR + 8 * REG_SP) >> +    ld.d    a0,    a2,    (KVM_ARCH_GGPR + 8 * REG_A0) >> +    ld.d    a1,    a2,    (KVM_ARCH_GGPR + 8 * REG_A1) >> +    ld.d    a3,    a2,    (KVM_ARCH_GGPR + 8 * REG_A3) >> +    ld.d    a4,    a2,    (KVM_ARCH_GGPR + 8 * REG_A4) >> +    ld.d    a5,    a2,    (KVM_ARCH_GGPR + 8 * REG_A5) >> +    ld.d    a6,    a2,    (KVM_ARCH_GGPR + 8 * REG_A6) >> +    ld.d    a7,    a2,    (KVM_ARCH_GGPR + 8 * REG_A7) >> +    ld.d    t0,    a2,    (KVM_ARCH_GGPR + 8 * REG_T0) >> +    ld.d    t1,    a2,    (KVM_ARCH_GGPR + 8 * REG_T1) >> +    ld.d    t2,    a2,    (KVM_ARCH_GGPR + 8 * REG_T2) >> +    ld.d    t3,    a2,    (KVM_ARCH_GGPR + 8 * REG_T3) >> +    ld.d    t4,    a2,    (KVM_ARCH_GGPR + 8 * REG_T4) >> +    ld.d    t5,    a2,    (KVM_ARCH_GGPR + 8 * REG_T5) >> +    ld.d    t6,    a2,    (KVM_ARCH_GGPR + 8 * REG_T6) >> +    ld.d    t7,    a2,    (KVM_ARCH_GGPR + 8 * REG_T7) >> +    ld.d    t8,    a2,    (KVM_ARCH_GGPR + 8 * REG_T8) >> +    ld.d    u0,    a2,    (KVM_ARCH_GGPR + 8 * REG_U0) >> +    ld.d    fp,    a2,    (KVM_ARCH_GGPR + 8 * REG_FP) >> +    ld.d    s0,    a2,    (KVM_ARCH_GGPR + 8 * REG_S0) >> +    ld.d    s1,    a2,    (KVM_ARCH_GGPR + 8 * REG_S1) >> +    ld.d    s2,    a2,    (KVM_ARCH_GGPR + 8 * REG_S2) >> +    ld.d    s3,    a2,    (KVM_ARCH_GGPR + 8 * REG_S3) >> +    ld.d    s4,    a2,    (KVM_ARCH_GGPR + 8 * REG_S4) >> +    ld.d    s5,    a2,    (KVM_ARCH_GGPR + 8 * REG_S5) >> +    ld.d    s6,    a2,    (KVM_ARCH_GGPR + 8 * REG_S6) >> +    ld.d    s7,    a2,    (KVM_ARCH_GGPR + 8 * REG_S7) >> +    ld.d    s8,    a2,    (KVM_ARCH_GGPR + 8 * REG_S8) > > Why not use .irp which like kvm_save/restore_host_gpr do here? Thanks, I will add kvm_restore_guest_gprs fucntion and use .irp statement to replace these instructions. > > >> +    /* Load KVM_ARCH register */ >> +    ld.d    a2,    a2,    (KVM_ARCH_GGPR + 8 * REG_A2) >> + >> +    ertn >> +.endm >> + >> +    /* >> +     * exception entry for general exception from guest mode >> +     *  - IRQ is disabled >> +     *  - kernel privilege in root mode >> +     *  - page mode keep unchanged from previous prmd in root mode >> +     *  - Fixme: tlb exception cannot happen since registers >> relative with TLB >> +     *  -        is still in guest mode, such as pgd table/vmid >> registers etc, >> +     *  -        will fix with hw page walk enabled in future >> +     * load kvm_vcpu from reserved CSR KVM_VCPU_KS, and save a2 to >> KVM_TEMP_KS >> +     */ >> +    .section    .text > > here. > > >> +    .cfi_sections    .debug_frame >> +SYM_CODE_START(kvm_vector_entry) >> +    csrwr    a2,   KVM_TEMP_KS >> +    csrrd    a2,   KVM_VCPU_KS >> +    addi.d    a2,   a2, KVM_VCPU_ARCH >> + >> +    /* After save gprs, free to use any gpr */ >> +    st.d    ra,    a2,    (KVM_ARCH_GGPR + 8 * REG_RA) >> +    st.d    tp,    a2,    (KVM_ARCH_GGPR + 8 * REG_TP) >> +    st.d    sp,    a2,    (KVM_ARCH_GGPR + 8 * REG_SP) >> +    st.d    a0,    a2,    (KVM_ARCH_GGPR + 8 * REG_A0) >> +    st.d    a1,    a2,    (KVM_ARCH_GGPR + 8 * REG_A1) >> +    st.d    a3,    a2,    (KVM_ARCH_GGPR + 8 * REG_A3) >> +    st.d    a4,    a2,    (KVM_ARCH_GGPR + 8 * REG_A4) >> +    st.d    a5,    a2,    (KVM_ARCH_GGPR + 8 * REG_A5) >> +    st.d    a6,    a2,    (KVM_ARCH_GGPR + 8 * REG_A6) >> +    st.d    a7,    a2,    (KVM_ARCH_GGPR + 8 * REG_A7) >> +    st.d    t0,    a2,    (KVM_ARCH_GGPR + 8 * REG_T0) >> +    st.d    t1,    a2,    (KVM_ARCH_GGPR + 8 * REG_T1) >> +    st.d    t2,    a2,    (KVM_ARCH_GGPR + 8 * REG_T2) >> +    st.d    t3,    a2,    (KVM_ARCH_GGPR + 8 * REG_T3) >> +    st.d    t4,    a2,    (KVM_ARCH_GGPR + 8 * REG_T4) >> +    st.d    t5,    a2,    (KVM_ARCH_GGPR + 8 * REG_T5) >> +    st.d    t6,    a2,    (KVM_ARCH_GGPR + 8 * REG_T6) >> +    st.d    t7,    a2,    (KVM_ARCH_GGPR + 8 * REG_T7) >> +    st.d    t8,    a2,    (KVM_ARCH_GGPR + 8 * REG_T8) >> +    st.d    u0,    a2,    (KVM_ARCH_GGPR + 8 * REG_U0) >> +    st.d    fp,    a2,    (KVM_ARCH_GGPR + 8 * REG_FP) >> +    st.d    s0,    a2,    (KVM_ARCH_GGPR + 8 * REG_S0) >> +    st.d    s1,    a2,    (KVM_ARCH_GGPR + 8 * REG_S1) >> +    st.d    s2,    a2,    (KVM_ARCH_GGPR + 8 * REG_S2) >> +    st.d    s3,    a2,    (KVM_ARCH_GGPR + 8 * REG_S3) >> +    st.d    s4,    a2,    (KVM_ARCH_GGPR + 8 * REG_S4) >> +    st.d    s5,    a2,    (KVM_ARCH_GGPR + 8 * REG_S5) >> +    st.d    s6,    a2,    (KVM_ARCH_GGPR + 8 * REG_S6) >> +    st.d    s7,    a2,    (KVM_ARCH_GGPR + 8 * REG_S7) >> +    st.d    s8,    a2,    (KVM_ARCH_GGPR + 8 * REG_S8) > > Why not .irp ... ? Thanks, I will add kvm_save_guest_gprs fucntion and use .irp statement to replace these instructions. > > >> +    /* Save guest a2 */ >> +    csrrd    t0,    KVM_TEMP_KS >> +    st.d    t0,    a2,    (KVM_ARCH_GGPR + 8 * REG_A2) >> + >> +    /* a2: kvm_vcpu_arch, a1 is free to use */ >> +    csrrd    s1,   KVM_VCPU_KS >> +    ld.d    s0,   s1, KVM_VCPU_RUN >> + >> +    csrrd    t0,   LOONGARCH_CSR_ESTAT >> +    st.d    t0,   a2, KVM_ARCH_HESTAT >> +    csrrd    t0,   LOONGARCH_CSR_ERA >> +    st.d    t0,   a2, KVM_ARCH_GPC >> +    csrrd    t0,   LOONGARCH_CSR_BADV >> +    st.d    t0,   a2, KVM_ARCH_HBADV >> +    csrrd    t0,   LOONGARCH_CSR_BADI >> +    st.d    t0,   a2, KVM_ARCH_HBADI >> + >> +    /* Restore host excfg.VS */ >> +    csrrd    t0, LOONGARCH_CSR_ECFG >> +    ld.d    t1, a2, KVM_ARCH_HECFG >> +    or    t0, t0, t1 >> +    csrwr    t0, LOONGARCH_CSR_ECFG >> + >> +    /* Restore host eentry */ >> +    ld.d    t0, a2, KVM_ARCH_HEENTRY >> +    csrwr    t0, LOONGARCH_CSR_EENTRY >> + >> +    /* restore host pgd table */ >> +    ld.d    t0, a2, KVM_ARCH_HPGD >> +    csrwr   t0, LOONGARCH_CSR_PGDL >> + >> +    /* >> +     * Disable PGM bit to enter root mode by default with next ertn >> +     */ >> +    ori    t0, zero, CSR_GSTAT_PVM > li.w >> +    csrxchg    zero, t0, LOONGARCH_CSR_GSTAT >> +    /* >> +     * Clear GTLBC.TGID field >> +     *       0: for root  tlb update in future tlb instr >> +     *  others: for guest tlb update like gpa to hpa in future tlb >> instr >> +     */ >> +    csrrd    t0, LOONGARCH_CSR_GTLBC >> +    bstrins.w    t0, zero, CSR_GTLBC_TGID_SHIFT_END, >> CSR_GTLBC_TGID_SHIFT >> +    csrwr    t0, LOONGARCH_CSR_GTLBC >> +    ld.d    tp, a2, KVM_ARCH_HTP >> +    ld.d    sp, a2, KVM_ARCH_HSP >> +    /* restore per cpu register */ >> +    ld.d    u0, a2, KVM_ARCH_HPERCPU >> +    addi.d    sp, sp, -PT_SIZE >> + >> +    /* Prepare handle exception */ >> +    or    a0, s0, zero > move >> +    or    a1, s1, zero > move >> +    ld.d    t8, a2, KVM_ARCH_HANDLE_EXIT >> +    jirl    ra, t8, 0 >> + >> +    or    a2, s1, zero > move >> +    addi.d    a2, a2, KVM_VCPU_ARCH >> + >> +    /* resume host when ret <= 0 */ >> +    bge    zero, a0, ret_to_host > blez a0, ret_to_host I think we need not to change it, as they have the same meaning. >> + >> +    /* >> +         * return to guest >> +         * save per cpu register again, maybe switched to another cpu >> +         */ >> +    st.d    u0, a2, KVM_ARCH_HPERCPU >> + >> +    /* Save kvm_vcpu to kscratch */ >> +    csrwr    s1, KVM_VCPU_KS >> +    kvm_switch_to_guest >> + >> +ret_to_host: >> +    ld.d    a2, a2, KVM_ARCH_HSP >> +    addi.d  a2, a2, -PT_SIZE >> +    kvm_restore_host_gpr    a2 >> +    jr      ra >> +SYM_CODE_END(kvm_vector_entry) >> +kvm_vector_entry_end: >> + >> +/* >> + * int kvm_enter_guest(struct kvm_run *run, struct kvm_vcpu *vcpu) >> + * >> + * @register_param: >> + *  a0: kvm_run* run >> + *  a1: kvm_vcpu* vcpu >> + */ >> +SYM_FUNC_START(kvm_enter_guest) >> +    /* allocate space in stack bottom */ >> +    addi.d    a2, sp, -PT_SIZE >> +    /* save host gprs */ >> +    kvm_save_host_gpr a2 >> + >> +    /* save host crmd,prmd csr to stack */ >> +    csrrd    a3, LOONGARCH_CSR_CRMD >> +    st.d    a3, a2, PT_CRMD >> +    csrrd    a3, LOONGARCH_CSR_PRMD >> +    st.d    a3, a2, PT_PRMD >> + >> +    addi.d    a2, a1, KVM_VCPU_ARCH >> +    st.d    sp, a2, KVM_ARCH_HSP >> +    st.d    tp, a2, KVM_ARCH_HTP >> +    /* Save per cpu register */ >> +    st.d    u0, a2, KVM_ARCH_HPERCPU >> + >> +    /* Save kvm_vcpu to kscratch */ >> +    csrwr    a1, KVM_VCPU_KS >> +    kvm_switch_to_guest >> +SYM_FUNC_END(kvm_enter_guest) >> +kvm_enter_guest_end: >> + >> +    .section ".rodata" >> +SYM_DATA(kvm_vector_size, .quad kvm_vector_entry_end - >> kvm_vector_entry) >> +SYM_DATA(kvm_enter_guest_size, .quad kvm_enter_guest_end - >> kvm_enter_guest) > > Not restore .text section. Although I'd like to use .pushsection ... .pop > > after marked kvm_..._end, you can put them after kvm_restore_fpu, too. > > > Jinyang Thanks, I will put these code after kvm_restore_fpu. Thanks Tianrui Zhao > > >> + >> + >> +SYM_FUNC_START(kvm_save_fpu) >> +    fpu_save_csr    a0 t1 >> +    fpu_save_double a0 t1 >> +    fpu_save_cc    a0 t1 t2 >> +    jr              ra >> +SYM_FUNC_END(kvm_save_fpu) >> + >> +SYM_FUNC_START(kvm_restore_fpu) >> +    fpu_restore_double a0 t1 >> +    fpu_restore_csr    a0 t1 >> +    fpu_restore_cc       a0 t1 t2 >> +    jr                 ra >> +SYM_FUNC_END(kvm_restore_fpu)