Received: by 2002:a05:7412:31a9:b0:e2:908c:2ebd with SMTP id et41csp5984863rdb; Sun, 17 Sep 2023 23:30:02 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHzD9e0VxH4O3YqRN2LzZnHTWzwLIVaYS8k1rLPXybiU9z5+3mZ+5DoGJROD3o6U02al6W9 X-Received: by 2002:a17:90a:f3c8:b0:274:c622:78cc with SMTP id ha8-20020a17090af3c800b00274c62278ccmr2875147pjb.30.1695018602064; Sun, 17 Sep 2023 23:30:02 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1695018602; cv=none; d=google.com; s=arc-20160816; b=ZDxQl8x4H0bIJaMl1aPYHsHmLt95n3z/lfUvysLXDBrdk0OBoz3yAXJ7EyK5y6f02h ymOq6URA5z9Zruzq82GloQe0OxPrKLfJqv5LFyz+XM4Q+UKx2hEDgCatw9iecxO9N/mL N4hqCMe+0x+fCG5p/WtbrZHAZS8nL3PKldC9Zj7zQrKhUTzoNA2Nr9uD+D8TFTwDqDJk 6aHyXGuQYcpB47MwuxiZLnpM2eiN1TyXoXSmA2bz4IIfg/y49pVqW21p5auhjilspbv+ HLs/iqI8XAWpFjvQWzvvJLU1ySIPPTRgnWo8pq5QgXgZ0dd8ySnWHAbDJhdnmnv3tckT 301A== 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=hVn6JZaT2DV/oLKsnmBK8wlKlvUQYq+eBYSfXYo2jV0=; fh=Ptk96Gsg/JRdkbGqFtqUh8lSmpX0OWY47f5l/BgQFhU=; b=yfQ9RR1UWFq1JD4QAsz975G9spZ472ZtGS1U+H9C5EiHcRWDQvrQQvXDB5r/sfd93/ JvzgqoR9FFYhJb03BvgpbAE1hLC4y+MwRv/XjDYCTZRdI5KDEAIUnKmIx7Cp4ljSalT9 A5n1pxhUEJBjpLDY5rkpFQirDVA/fWwiTjtgalZE9UoF6hSX/qiJn7EmDkKsC0mgPcd0 r9MGLTcFzg2yhAD9PtH+mCYly7IbdP27/W2AnZwabBtO1DDpSpHuQIDSD1xuHXS2kwDM 2LfuxLEFLsEOWEOysXoEbKqPSSGDXc7mkFlU29GKRow83+sSTq/QbWGOXO1GmaHFHdvB FCfA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:6 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from pete.vger.email (pete.vger.email. [2620:137:e000::3:6]) by mx.google.com with ESMTPS id ne10-20020a17090b374a00b00262ebe643a2si7424134pjb.186.2023.09.17.23.30.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 17 Sep 2023 23:30:02 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:6 as permitted sender) client-ip=2620:137:e000::3:6; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:6 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by pete.vger.email (Postfix) with ESMTP id 162D680811ED; Sun, 17 Sep 2023 23:26:21 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at pete.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239784AbjIRGZ1 (ORCPT + 99 others); Mon, 18 Sep 2023 02:25:27 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36670 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239838AbjIRGZV (ORCPT ); Mon, 18 Sep 2023 02:25:21 -0400 Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id E444F8F; Sun, 17 Sep 2023 23:25:11 -0700 (PDT) Received: from loongson.cn (unknown [10.40.46.158]) by gateway (Coremail) with SMTP id _____8Bx5fBG7QdlBIYpAA--.14425S3; Mon, 18 Sep 2023 14:25:10 +0800 (CST) Received: from [192.168.124.126] (unknown [10.40.46.158]) by localhost.localdomain (Coremail) with SMTP id AQAAf8DxkN1B7QdlsyoKAA--.22352S3; Mon, 18 Sep 2023 14:25:08 +0800 (CST) Subject: Re: [PATCH v21 02/29] LoongArch: KVM: Implement kvm module related interface To: Huacai Chen Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Paolo Bonzini , WANG Xuerui , Greg Kroah-Hartman , loongarch@lists.linux.dev, Jens Axboe , Mark Brown , Alex Deucher , Oliver Upton , maobibo@loongson.cn, Xi Ruoyao References: <20230915014949.1222777-1-zhaotianrui@loongson.cn> <20230915014949.1222777-3-zhaotianrui@loongson.cn> <525aa9e2-1ebc-6c49-55ef-9f3c7d18d3e0@loongson.cn> <8e23325a-b4d3-db80-7d65-ebadcd3ef5a9@loongson.cn> From: zhaotianrui Message-ID: Date: Mon, 18 Sep 2023 14:25:05 +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: AQAAf8DxkN1B7QdlsyoKAA--.22352S3 X-CM-SenderInfo: p2kd03xldq233l6o00pqjv00gofq/ X-Coremail-Antispam: 1Uk129KBj9fXoW3Kw1kAr1fCr45uw1DWFWDZFc_yoW8CF43Zo WrKF4fJF1UJr1UJrsrG34qqay0yw15GrWFqa4UJrn5Jw1Dtw13ZrW5C3WUJrsxWr1UAr1U JayqgF409FW2gr15l-sFpf9Il3svdjkaLaAFLSUrUUUUeb8apTn2vfkv8UJUUUU8wcxFpf 9Il3svdxBIdaVrn0xqx4xG64xvF2IEw4CE5I8CrVC2j2Jv73VFW2AGmfu7bjvjm3AaLaJ3 UjIYCTnIWjp_UUUO57kC6x804xWl14x267AKxVWUJVW8JwAFc2x0x2IEx4CE42xK8VAvwI 8IcIk0rVWrJVCq3wAFIxvE14AKwVWUXVWUAwA2ocxC64kIII0Yj41l84x0c7CEw4AK67xG Y2AK021l84ACjcxK6xIIjxv20xvE14v26r4j6ryUM28EF7xvwVC0I7IYx2IY6xkF7I0E14 v26r4j6F4UM28EF7xvwVC2z280aVAFwI0_Gr1j6F4UJwA2z4x0Y4vEx4A2jsIEc7CjxVAF wI0_Gr1j6F4UJwAaw2AFwI0_JF0_Jw1le2I262IYc4CY6c8Ij28IcVAaY2xG8wAqjxCEc2 xF0cIa020Ex4CE44I27wAqx4xG64xvF2IEw4CE5I8CrVC2j2WlYx0E2Ix0cI8IcVAFwI0_ JF0_Jw1lYx0Ex4A2jsIE14v26F4j6r4UJwAm72CE4IkC6x0Yz7v_Jr0_Gr1lF7xvr2IY64 vIr41lc7I2V7IY0VAS07AlzVAYIcxG8wCY1x0262kKe7AKxVWUAVWUtwCF04k20xvY0x0E wIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwCFI7km07C267AKxVWUAVWUtwC20s026c02F4 0E14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_Jw0_GFyl IxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVWUCVW8JwCI42IY6xIIjxv20xvEc7CjxV AFwI0_Jr0_Gr1lIxAIcVCF04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26F4j 6r4UJwCI42IY6I8E87Iv6xkF7I0E14v26r4j6r4UJbIYCTnIWIevJa73UjIFyTuYvjxU7p nQUUUUU X-Spam-Status: No, score=-2.2 required=5.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,NICE_REPLY_A,SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on pete.vger.email Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (pete.vger.email [0.0.0.0]); Sun, 17 Sep 2023 23:26:21 -0700 (PDT) 在 2023/9/18 下午12:03, Huacai Chen 写道: > On Mon, Sep 18, 2023 at 11:20 AM zhaotianrui wrote: >> >> 在 2023/9/18 上午11:12, Huacai Chen 写道: >>> On Mon, Sep 18, 2023 at 11:08 AM zhaotianrui wrote: >>>> 在 2023/9/18 上午9:45, Huacai Chen 写道: >>>>> On Mon, Sep 18, 2023 at 9:21 AM zhaotianrui wrote: >>>>>> 在 2023/9/16 下午4:51, Huacai Chen 写道: >>>>>>> Hi, Tianrui, >>>>>>> >>>>>>> On Fri, Sep 15, 2023 at 9:50 AM Tianrui Zhao wrote: >>>>>>>> Implement LoongArch kvm module init, module exit interface, >>>>>>>> using kvm context to save the vpid info and vcpu world switch >>>>>>>> interface pointer. >>>>>>>> >>>>>>>> Reviewed-by: Bibo Mao >>>>>>>> Signed-off-by: Tianrui Zhao >>>>>>>> --- >>>>>>>> arch/loongarch/kvm/main.c | 367 ++++++++++++++++++++++++++++++++++++++ >>>>>>>> 1 file changed, 367 insertions(+) >>>>>>>> create mode 100644 arch/loongarch/kvm/main.c >>>>>>>> >>>>>>>> diff --git a/arch/loongarch/kvm/main.c b/arch/loongarch/kvm/main.c >>>>>>>> new file mode 100644 >>>>>>>> index 0000000000..0deb9273d8 >>>>>>>> --- /dev/null >>>>>>>> +++ b/arch/loongarch/kvm/main.c >>>>>>>> @@ -0,0 +1,367 @@ >>>>>>>> +// SPDX-License-Identifier: GPL-2.0 >>>>>>>> +/* >>>>>>>> + * Copyright (C) 2020-2023 Loongson Technology Corporation Limited >>>>>>>> + */ >>>>>>>> + >>>>>>>> +#include >>>>>>>> +#include >>>>>>>> +#include >>>>>>>> +#include >>>>>>>> +#include >>>>>>>> +#include >>>>>>>> +#include "trace.h" >>>>>>>> + >>>>>>>> +static struct kvm_context __percpu *vmcs; >>>>>>>> +struct kvm_world_switch *kvm_loongarch_ops; >>>>>>>> +unsigned long vpid_mask; >>>>>>>> +static int gcsr_flag[CSR_MAX_NUMS]; >>>>>>>> + >>>>>>>> +int get_gcsr_flag(int csr) >>>>>>>> +{ >>>>>>>> + if (csr < CSR_MAX_NUMS) >>>>>>>> + return gcsr_flag[csr]; >>>>>>>> + >>>>>>>> + return INVALID_GCSR; >>>>>>>> +} >>>>>>>> + >>>>>>>> +static inline void set_gcsr_sw_flag(int csr) >>>>>>>> +{ >>>>>>>> + if (csr < CSR_MAX_NUMS) >>>>>>>> + gcsr_flag[csr] |= SW_GCSR; >>>>>>>> +} >>>>>>>> + >>>>>>>> +static inline void set_gcsr_hw_flag(int csr) >>>>>>>> +{ >>>>>>>> + if (csr < CSR_MAX_NUMS) >>>>>>>> + gcsr_flag[csr] |= HW_GCSR; >>>>>>>> +} >>>>>>>> + >>>>>>>> +/* >>>>>>>> + * The default value of gcsr_flag[CSR] is 0, and we use this >>>>>>>> + * function to set the flag to 1(SW_GCSR) or 2(HW_GCSR) if the >>>>>>>> + * gcsr is software or hardware. It will be used by get/set_gcsr, >>>>>>>> + * if gcsr_flag is HW we should use gcsrrd/gcsrwr to access it, >>>>>>>> + * else use sw csr to emulate it. >>>>>>>> + */ >>>>>>>> +static void kvm_init_gcsr_flag(void) >>>>>>>> +{ >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_CRMD); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_PRMD); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_EUEN); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_MISC); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_ECFG); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_ESTAT); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_ERA); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_BADV); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_BADI); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_EENTRY); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_TLBIDX); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_TLBEHI); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_TLBELO0); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_TLBELO1); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_ASID); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_PGDL); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_PGDH); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_PWCTL0); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_PWCTL1); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_STLBPGSIZE); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_RVACFG); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_CPUID); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_PRCFG1); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_PRCFG2); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_PRCFG3); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_KS0); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_KS1); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_KS2); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_KS3); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_KS4); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_KS5); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_KS6); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_KS7); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_TMID); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_TCFG); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_TVAL); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_CNTC); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_LLBCTL); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_TLBRENTRY); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_TLBRBADV); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_TLBRERA); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_TLBRSAVE); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_TLBRELO0); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_TLBRELO1); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_TLBREHI); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_TLBRPRMD); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_DMWIN0); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_DMWIN1); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_DMWIN2); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_DMWIN3); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_MWPS); >>>>>>>> + set_gcsr_hw_flag(LOONGARCH_CSR_FWPS); >>>>>>>> + >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_IMPCTL1); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_IMPCTL2); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_MERRCTL); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_MERRINFO1); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_MERRINFO2); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_MERRENTRY); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_MERRERA); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_MERRSAVE); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_CTAG); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_DEBUG); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_DERA); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_DESAVE); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_PRCFG1); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_PRCFG2); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_PRCFG3); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_PGD); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_TINTCLR); >>>>>>>> + >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_FWPS); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_FWPC); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_MWPS); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_MWPC); >>>>>>> FWPS and MWPS are both HW CSR and SW CSR? >>>>>>> >>>>>>> Huacai >>>>>> The FWPC and MWPC should be SW GCSR, FWPS and MWPS should be HW GCSR, it >>>>>> is my mistake. >>>>> But in user manual vol 3, section 1.5, FWPC/FWPS/MWPC/MWPS are all HW >>>>> GCSR, while DBxxxx and IBxxxx are SW GCSR. >>>> Ok, It is my misunderstanding, as the FWPC and MWPC can control guest >>>> debug register numbers, but I know they are all HW GCSR when I look up >>>> the manual again. >>> So these lines can be removed? >>> >>> set_gcsr_sw_flag(LOONGARCH_CSR_FWPS); >>> set_gcsr_sw_flag(LOONGARCH_CSR_FWPC); >>> set_gcsr_sw_flag(LOONGARCH_CSR_MWPS); >>> set_gcsr_sw_flag(LOONGARCH_CSR_MWPC); >>> >>> And add FWPC/MWPC to hw list? > Can you discuss more with our hw engineers? I found in section 1.8: > PGD, TINTCLR, PRCFG1~3 are all HW GCSR. If guest can access hw CSR directly and do not cause a exception, it means hw GCSR. on the other hand, if cause a exception to return to KVM to emulate it by software, it means SW GCSR. And I re-check the PGD, TINTCLR, PRCFG1~3 CSR, they should be hw GCSR. Thanks Tianrui Zhao > > Huacai > >>> Huacai >> Yes, It is. >> >> Thanks >> Tianrui Zhao >>>> Thanks >>>> Tianrui Zhao >>>>> Huacai >>>>> >>>>>> Thanks >>>>>> Tianrui Zhao >>>>>>>> + >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_DB0ADDR); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_DB0MASK); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_DB0CTRL); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_DB0ASID); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_DB1ADDR); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_DB1MASK); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_DB1CTRL); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_DB1ASID); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_DB2ADDR); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_DB2MASK); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_DB2CTRL); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_DB2ASID); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_DB3ADDR); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_DB3MASK); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_DB3CTRL); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_DB3ASID); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_DB4ADDR); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_DB4MASK); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_DB4CTRL); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_DB4ASID); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_DB5ADDR); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_DB5MASK); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_DB5CTRL); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_DB5ASID); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_DB6ADDR); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_DB6MASK); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_DB6CTRL); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_DB6ASID); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_DB7ADDR); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_DB7MASK); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_DB7CTRL); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_DB7ASID); >>>>>>>> + >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_IB0ADDR); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_IB0MASK); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_IB0CTRL); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_IB0ASID); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_IB1ADDR); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_IB1MASK); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_IB1CTRL); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_IB1ASID); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_IB2ADDR); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_IB2MASK); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_IB2CTRL); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_IB2ASID); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_IB3ADDR); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_IB3MASK); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_IB3CTRL); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_IB3ASID); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_IB4ADDR); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_IB4MASK); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_IB4CTRL); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_IB4ASID); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_IB5ADDR); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_IB5MASK); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_IB5CTRL); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_IB5ASID); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_IB6ADDR); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_IB6MASK); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_IB6CTRL); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_IB6ASID); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_IB7ADDR); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_IB7MASK); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_IB7CTRL); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_IB7ASID); >>>>>>>> + >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_PERFCTRL0); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_PERFCNTR0); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_PERFCTRL1); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_PERFCNTR1); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_PERFCTRL2); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_PERFCNTR2); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_PERFCTRL3); >>>>>>>> + set_gcsr_sw_flag(LOONGARCH_CSR_PERFCNTR3); >>>>>>>> +} >>>>>>>> + >>>>>>>> +static void kvm_update_vpid(struct kvm_vcpu *vcpu, int cpu) >>>>>>>> +{ >>>>>>>> + struct kvm_context *context; >>>>>>>> + unsigned long vpid; >>>>>>>> + >>>>>>>> + context = per_cpu_ptr(vcpu->kvm->arch.vmcs, cpu); >>>>>>>> + vpid = context->vpid_cache + 1; >>>>>>>> + if (!(vpid & vpid_mask)) { >>>>>>>> + /* finish round of 64 bit loop */ >>>>>>>> + if (unlikely(!vpid)) >>>>>>>> + vpid = vpid_mask + 1; >>>>>>>> + >>>>>>>> + /* vpid 0 reserved for root */ >>>>>>>> + ++vpid; >>>>>>>> + >>>>>>>> + /* start new vpid cycle */ >>>>>>>> + kvm_flush_tlb_all(); >>>>>>>> + } >>>>>>>> + >>>>>>>> + context->vpid_cache = vpid; >>>>>>>> + vcpu->arch.vpid = vpid; >>>>>>>> +} >>>>>>>> + >>>>>>>> +void kvm_check_vpid(struct kvm_vcpu *vcpu) >>>>>>>> +{ >>>>>>>> + struct kvm_context *context; >>>>>>>> + bool migrated; >>>>>>>> + unsigned long ver, old, vpid; >>>>>>>> + int cpu; >>>>>>>> + >>>>>>>> + cpu = smp_processor_id(); >>>>>>>> + /* >>>>>>>> + * Are we entering guest context on a different CPU to last time? >>>>>>>> + * If so, the vCPU's guest TLB state on this CPU may be stale. >>>>>>>> + */ >>>>>>>> + context = per_cpu_ptr(vcpu->kvm->arch.vmcs, cpu); >>>>>>>> + migrated = (vcpu->cpu != cpu); >>>>>>>> + >>>>>>>> + /* >>>>>>>> + * Check if our vpid is of an older version >>>>>>>> + * >>>>>>>> + * We also discard the stored vpid if we've executed on >>>>>>>> + * another CPU, as the guest mappings may have changed without >>>>>>>> + * hypervisor knowledge. >>>>>>>> + */ >>>>>>>> + ver = vcpu->arch.vpid & ~vpid_mask; >>>>>>>> + old = context->vpid_cache & ~vpid_mask; >>>>>>>> + if (migrated || (ver != old)) { >>>>>>>> + kvm_update_vpid(vcpu, cpu); >>>>>>>> + trace_kvm_vpid_change(vcpu, vcpu->arch.vpid); >>>>>>>> + vcpu->cpu = cpu; >>>>>>>> + } >>>>>>>> + >>>>>>>> + /* Restore GSTAT(0x50).vpid */ >>>>>>>> + vpid = (vcpu->arch.vpid & vpid_mask) << CSR_GSTAT_GID_SHIFT; >>>>>>>> + change_csr_gstat(vpid_mask << CSR_GSTAT_GID_SHIFT, vpid); >>>>>>>> +} >>>>>>>> + >>>>>>>> +static int kvm_loongarch_env_init(void) >>>>>>>> +{ >>>>>>>> + struct kvm_context *context; >>>>>>>> + int cpu, order; >>>>>>>> + void *addr; >>>>>>>> + >>>>>>>> + vmcs = alloc_percpu(struct kvm_context); >>>>>>>> + if (!vmcs) { >>>>>>>> + pr_err("kvm: failed to allocate percpu kvm_context\n"); >>>>>>>> + return -ENOMEM; >>>>>>>> + } >>>>>>>> + >>>>>>>> + kvm_loongarch_ops = kzalloc(sizeof(*kvm_loongarch_ops), GFP_KERNEL); >>>>>>>> + if (!kvm_loongarch_ops) { >>>>>>>> + free_percpu(vmcs); >>>>>>>> + vmcs = NULL; >>>>>>>> + return -ENOMEM; >>>>>>>> + } >>>>>>>> + /* >>>>>>>> + * There will be problem in world switch code if there >>>>>>>> + * is page fault reenter, since pgd register is shared >>>>>>>> + * between root kernel and kvm hypervisor. World switch >>>>>>>> + * entry need be unmapped area, cannot be tlb mapped area. >>>>>>>> + * In future if hw pagetable walking is supported, or there >>>>>>>> + * is separate pgd registers between root kernel and kvm >>>>>>>> + * hypervisor, copying about world switch code will not be used. >>>>>>>> + */ >>>>>>>> + >>>>>>>> + order = get_order(kvm_vector_size + kvm_enter_guest_size); >>>>>>>> + addr = (void *)__get_free_pages(GFP_KERNEL, order); >>>>>>>> + if (!addr) { >>>>>>>> + free_percpu(vmcs); >>>>>>>> + vmcs = NULL; >>>>>>>> + kfree(kvm_loongarch_ops); >>>>>>>> + kvm_loongarch_ops = NULL; >>>>>>>> + return -ENOMEM; >>>>>>>> + } >>>>>>>> + >>>>>>>> + memcpy(addr, kvm_vector_entry, kvm_vector_size); >>>>>>>> + memcpy(addr + kvm_vector_size, kvm_enter_guest, kvm_enter_guest_size); >>>>>>>> + flush_icache_range((unsigned long)addr, (unsigned long)addr + >>>>>>>> + kvm_vector_size + kvm_enter_guest_size); >>>>>>>> + kvm_loongarch_ops->guest_eentry = addr; >>>>>>>> + kvm_loongarch_ops->enter_guest = addr + kvm_vector_size; >>>>>>>> + kvm_loongarch_ops->page_order = order; >>>>>>>> + >>>>>>>> + vpid_mask = read_csr_gstat(); >>>>>>>> + vpid_mask = (vpid_mask & CSR_GSTAT_GIDBIT) >> CSR_GSTAT_GIDBIT_SHIFT; >>>>>>>> + if (vpid_mask) >>>>>>>> + vpid_mask = GENMASK(vpid_mask - 1, 0); >>>>>>>> + >>>>>>>> + for_each_possible_cpu(cpu) { >>>>>>>> + context = per_cpu_ptr(vmcs, cpu); >>>>>>>> + context->vpid_cache = vpid_mask + 1; >>>>>>>> + context->last_vcpu = NULL; >>>>>>>> + } >>>>>>>> + >>>>>>>> + kvm_init_fault(); >>>>>>>> + kvm_init_gcsr_flag(); >>>>>>>> + >>>>>>>> + return 0; >>>>>>>> +} >>>>>>>> + >>>>>>>> +static void kvm_loongarch_env_exit(void) >>>>>>>> +{ >>>>>>>> + unsigned long addr; >>>>>>>> + >>>>>>>> + if (vmcs) >>>>>>>> + free_percpu(vmcs); >>>>>>>> + >>>>>>>> + if (kvm_loongarch_ops) { >>>>>>>> + if (kvm_loongarch_ops->guest_eentry) { >>>>>>>> + addr = (unsigned long)kvm_loongarch_ops->guest_eentry; >>>>>>>> + free_pages(addr, kvm_loongarch_ops->page_order); >>>>>>>> + } >>>>>>>> + kfree(kvm_loongarch_ops); >>>>>>>> + } >>>>>>>> +} >>>>>>>> + >>>>>>>> +static int kvm_loongarch_init(void) >>>>>>>> +{ >>>>>>>> + int r; >>>>>>>> + >>>>>>>> + if (!cpu_has_lvz) { >>>>>>>> + kvm_info("hardware virtualization not available\n"); >>>>>>>> + return -ENODEV; >>>>>>>> + } >>>>>>>> + r = kvm_loongarch_env_init(); >>>>>>>> + if (r) >>>>>>>> + return r; >>>>>>>> + >>>>>>>> + return kvm_init(sizeof(struct kvm_vcpu), 0, THIS_MODULE); >>>>>>>> +} >>>>>>>> + >>>>>>>> +static void kvm_loongarch_exit(void) >>>>>>>> +{ >>>>>>>> + kvm_exit(); >>>>>>>> + kvm_loongarch_env_exit(); >>>>>>>> +} >>>>>>>> + >>>>>>>> +module_init(kvm_loongarch_init); >>>>>>>> +module_exit(kvm_loongarch_exit); >>>>>>>> + >>>>>>>> +#ifdef MODULE >>>>>>>> +static const struct cpu_feature loongarch_kvm_feature[] = { >>>>>>>> + { .feature = cpu_feature(LOONGARCH_LVZ) }, >>>>>>>> + {}, >>>>>>>> +}; >>>>>>>> +MODULE_DEVICE_TABLE(cpu, loongarch_kvm_feature); >>>>>>>> +#endif >>>>>>>> -- >>>>>>>> 2.39.1 >>>>>>>> >>