Received: by 2002:ab2:7b86:0:b0:1f7:5705:b850 with SMTP id q6csp1274453lqh; Mon, 6 May 2024 02:36:02 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCUU2qdqJdSpErWyMa0g2TZkUCBz7hFC8gUUvd67ITwqLuTX5aJWWczwqYdkDuMIbOPBV2xXS+sOee3vGJcS7Bd6kFxPh8Fwb1e6yGFRzA== X-Google-Smtp-Source: AGHT+IH6lp7ATkRSXEp/+6uoroQ8GK2kSwou8ZLMH7afn5/IsCdVv3UTs19PaspQdMoazUCDv7I3 X-Received: by 2002:a05:6870:911e:b0:23c:a6f8:9362 with SMTP id o30-20020a056870911e00b0023ca6f89362mr13072180oae.13.1714988162263; Mon, 06 May 2024 02:36:02 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1714988162; cv=pass; d=google.com; s=arc-20160816; b=0i15sYVUA+YEIjSbjyaGMUd8+u1/P2i79idY4DULWDNEoRGqiOq/vTAsnrp8mm5Uxg JEW+BB2qQWOKpTDo/EtCdGquLryQ43Yj39AfG9THAS+fIy/GDvv5AfptLTOIKL2sJy84 lmJVn38ZXizTJ8IQTdXmLKsLAC2ABP6UfCzkZYDSMJu9+6oghm8Pwzlmc60svoA/eSO+ DZ6OShkmiGQk2OUsC+MhVEXq0qFMh4NmqjUFdzISq2xnz5IviJTicfZiVvaIT+RpzupY 7uHKniPTFoyjSCJw83QrezTTYsVI8HMhQcecB9gkL05yEpt+yROdZnG5jVYKwlmU1ITs zBbw== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:content-language:in-reply-to:mime-version :list-unsubscribe:list-subscribe:list-id:precedence:user-agent:date :message-id:from:references:cc:to:subject; bh=Gk8tmFdolFW6can8UiAqOjyY1NTXF5x3w65FOjWKjYA=; fh=CXs9v6wxz1RS3jNhqU8uet3La6EKRrcyqg/6VK5sq6E=; b=i0JgkcScFgtZl18D01yRxL016mjwwmi26UNxZaHiRWek1h3i2m/FHaiARw1SVEmtUT e00SO4PXtssn71xSmwluALI/ul1aGRHAjc9WKg02nKEZiDVPq4TKXGdNF4La2vqgsMZu IXPqifRRlvdoVYwByKQyzzf7d81y+u8n96pIPWsFCUlzla1GGr21ZoihzlWro7No/wRc 84rlMUJ/3SXtRWkowS7eVxn4ygZrkEhrPAS13ggJeG//JkhtqlZdBXH3HeiOhUAXkCGw ZHqtehDQOyWIrpqtK9FqbmrHSJJzHSZiOXGeUpmJCVnzzkc344BQWHVk10geV8ts2Smc M6+g==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; arc=pass (i=1 spf=pass spfdomain=loongson.cn); spf=pass (google.com: domain of linux-kernel+bounces-169576-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-169576-linux.lists.archive=gmail.com@vger.kernel.org" Return-Path: Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [2604:1380:45e3:2400::1]) by mx.google.com with ESMTPS id r29-20020a638f5d000000b0061ec242496asi5736991pgn.47.2024.05.06.02.36.01 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 06 May 2024 02:36:02 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel+bounces-169576-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) client-ip=2604:1380:45e3:2400::1; Authentication-Results: mx.google.com; arc=pass (i=1 spf=pass spfdomain=loongson.cn); spf=pass (google.com: domain of linux-kernel+bounces-169576-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-169576-linux.lists.archive=gmail.com@vger.kernel.org" Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sv.mirrors.kernel.org (Postfix) with ESMTPS id 6158828131A for ; Mon, 6 May 2024 09:35:37 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id A056514264C; Mon, 6 May 2024 09:35:21 +0000 (UTC) Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by smtp.subspace.kernel.org (Postfix) with ESMTP id E966A1422AC; Mon, 6 May 2024 09:35:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=114.242.206.163 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714988120; cv=none; b=mSXx9yq3tOdTKy4A+HLk7f77ygUMZHW4+ZL2tRnV60xihuhAUXAiM2dVUwYtn83/ejKbuzUbkvQiqreSVt/YxgwG58EQjvkzpOjZHXbTc0kMQBNuUPGT9hvZyGHTgfDj1GO9Kw1yg3pdjxVgFB3YRd65O5YVD+K4U/TqHQS4bpI= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714988120; c=relaxed/simple; bh=UouzFmAZvXH2lR+ToTOzIzujl3lEebLIantGL5V0TEA=; h=Subject:To:Cc:References:From:Message-ID:Date:MIME-Version: In-Reply-To:Content-Type; b=LJooEhBpvJVFU55o1ovndy1jILxXcKuXPwQWOzAWiKevZiUy6wygkXFuympawGjEiYJFoatJQumo+IPyzF3fi0yTjWjCEgfH0Zzh/7IhxDgJtAIimIRhHuntdPjwa2epojFCEYDy8pFgYyl/eZxmpC+yb2T3qTKYg3jQ5l9Cl7E= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn; spf=pass smtp.mailfrom=loongson.cn; arc=none smtp.client-ip=114.242.206.163 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=loongson.cn Received: from loongson.cn (unknown [10.20.42.173]) by gateway (Coremail) with SMTP id _____8BxV_BRpDhm_BcIAA--.22854S3; Mon, 06 May 2024 17:35:13 +0800 (CST) Received: from [10.20.42.173] (unknown [10.20.42.173]) by localhost.localdomain (Coremail) with SMTP id AQAAf8Ax691NpDhmtWoSAA--.37507S3; Mon, 06 May 2024 17:35:11 +0800 (CST) Subject: Re: [PATCH v8 4/6] LoongArch: KVM: Add vcpu search support from physical cpuid To: Huacai Chen Cc: Tianrui Zhao , Juergen Gross , Paolo Bonzini , Jonathan Corbet , loongarch@lists.linux.dev, linux-kernel@vger.kernel.org, virtualization@lists.linux.dev, kvm@vger.kernel.org References: <20240428100518.1642324-1-maobibo@loongson.cn> <20240428100518.1642324-5-maobibo@loongson.cn> <7335dcde-1b3a-1260-ac62-d2d9fcbd6a78@loongson.cn> From: maobibo Message-ID: <540aa8dd-eada-1f77-0a20-38196fb5472a@loongson.cn> Date: Mon, 6 May 2024 17:35:07 +0800 User-Agent: Mozilla/5.0 (X11; Linux loongarch64; rv:68.0) Gecko/20100101 Thunderbird/68.7.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 8bit X-CM-TRANSID:AQAAf8Ax691NpDhmtWoSAA--.37507S3 X-CM-SenderInfo: xpdruxter6z05rqj20fqof0/ X-Coremail-Antispam: 1Uk129KBj93XoW3ur47Kw4kWF13AF47Jr4kZrc_yoWkCrW8pr yUCa1Dur48Jr17Jw10qw1q9rnIyry8Kr17ZasrKa45Jr1qvr13Jr4kJryUCF1kJr1rGF4I qr1UJ3W3uFWFyacCm3ZEXasCq-sJn29KB7ZKAUJUUUU7529EdanIXcx71UUUUU7KY7ZEXa sCq-sGcSsGvfJ3Ic02F40EFcxC0VAKzVAqx4xG6I80ebIjqfuFe4nvWSU5nxnvy29KBjDU 0xBIdaVrnRJUUUPab4IE77IF4wAFF20E14v26r1j6r4UM7CY07I20VC2zVCF04k26cxKx2 IYs7xG6rWj6s0DM7CIcVAFz4kK6r1Y6r17M28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48v e4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_Gr0_Xr1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI 0_Gr0_Cr1l84ACjcxK6I8E87Iv67AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVCY1x0267AK xVW8Jr0_Cr1UM2kKe7AKxVWUXVWUAwAS0I0E0xvYzxvE52x082IY62kv0487Mc804VCY07 AIYIkI8VC2zVCFFI0UMc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VC0I7IYx2IY67AKxVWU AVWUtwAv7VC2z280aVAFwI0_Gr0_Cr1lOx8S6xCaFVCjc4AY6r1j6r4UM4x0Y48IcVAKI4 8JMxk0xIA0c2IEe2xFo4CEbIxvr21lc7CjxVAaw2AFwI0_JF0_Jw1l42xK82IYc2Ij64vI r41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1l4IxYO2xFxVAFwI0_Jrv_JF1lx2IqxVAqx4xG67 AKxVWUJVWUGwC20s026x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26r1q6r43MIIY rxkI7VAKI48JMIIF0xvE2Ix0cI8IcVAFwI0_Jr0_JF4lIxAIcVC0I7IYx2IY6xkF7I0E14 v26r1j6r4UMIIF0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVW8JVWx JwCI42IY6I8E87Iv6xkF7I0E14v26r4j6r4UJbIYCTnIWIevJa73UjIFyTuYvjxUxYiiDU UUU On 2024/5/6 下午4:59, Huacai Chen wrote: > On Mon, May 6, 2024 at 4:18 PM maobibo wrote: >> >> >> >> On 2024/5/6 下午3:06, Huacai Chen wrote: >>> Hi, Bibo, >>> >>> On Mon, May 6, 2024 at 2:36 PM maobibo wrote: >>>> >>>> >>>> >>>> On 2024/5/6 上午9:49, Huacai Chen wrote: >>>>> Hi, Bibo, >>>>> >>>>> On Sun, Apr 28, 2024 at 6:05 PM Bibo Mao wrote: >>>>>> >>>>>> Physical cpuid is used for interrupt routing for irqchips such as >>>>>> ipi/msi/extioi interrupt controller. And physical cpuid is stored >>>>>> at CSR register LOONGARCH_CSR_CPUID, it can not be changed once vcpu >>>>>> is created and physical cpuid of two vcpus cannot be the same. >>>>>> >>>>>> Different irqchips have different size declaration about physical cpuid, >>>>>> max cpuid value for CSR LOONGARCH_CSR_CPUID on 3A5000 is 512, max cpuid >>>>>> supported by IPI hardware is 1024, 256 for extioi irqchip, and 65536 >>>>>> for MSI irqchip. >>>>>> >>>>>> The smallest value from all interrupt controllers is selected now, >>>>>> and the max cpuid size is defines as 256 by KVM which comes from >>>>>> extioi irqchip. >>>>>> >>>>>> Signed-off-by: Bibo Mao >>>>>> --- >>>>>> arch/loongarch/include/asm/kvm_host.h | 26 ++++++++ >>>>>> arch/loongarch/include/asm/kvm_vcpu.h | 1 + >>>>>> arch/loongarch/kvm/vcpu.c | 93 ++++++++++++++++++++++++++- >>>>>> arch/loongarch/kvm/vm.c | 11 ++++ >>>>>> 4 files changed, 130 insertions(+), 1 deletion(-) >>>>>> >>>>>> diff --git a/arch/loongarch/include/asm/kvm_host.h b/arch/loongarch/include/asm/kvm_host.h >>>>>> index 2d62f7b0d377..3ba16ef1fe69 100644 >>>>>> --- a/arch/loongarch/include/asm/kvm_host.h >>>>>> +++ b/arch/loongarch/include/asm/kvm_host.h >>>>>> @@ -64,6 +64,30 @@ struct kvm_world_switch { >>>>>> >>>>>> #define MAX_PGTABLE_LEVELS 4 >>>>>> >>>>>> +/* >>>>>> + * Physical cpu id is used for interrupt routing, there are different >>>>>> + * definitions about physical cpuid on different hardwares. >>>>>> + * For LOONGARCH_CSR_CPUID register, max cpuid size if 512 >>>>>> + * For IPI HW, max dest CPUID size 1024 >>>>>> + * For extioi interrupt controller, max dest CPUID size is 256 >>>>>> + * For MSI interrupt controller, max supported CPUID size is 65536 >>>>>> + * >>>>>> + * Currently max CPUID is defined as 256 for KVM hypervisor, in future >>>>>> + * it will be expanded to 4096, including 16 packages at most. And every >>>>>> + * package supports at most 256 vcpus >>>>>> + */ >>>>>> +#define KVM_MAX_PHYID 256 >>>>>> + >>>>>> +struct kvm_phyid_info { >>>>>> + struct kvm_vcpu *vcpu; >>>>>> + bool enabled; >>>>>> +}; >>>>>> + >>>>>> +struct kvm_phyid_map { >>>>>> + int max_phyid; >>>>>> + struct kvm_phyid_info phys_map[KVM_MAX_PHYID]; >>>>>> +}; >>>>>> + >>>>>> struct kvm_arch { >>>>>> /* Guest physical mm */ >>>>>> kvm_pte_t *pgd; >>>>>> @@ -71,6 +95,8 @@ struct kvm_arch { >>>>>> unsigned long invalid_ptes[MAX_PGTABLE_LEVELS]; >>>>>> unsigned int pte_shifts[MAX_PGTABLE_LEVELS]; >>>>>> unsigned int root_level; >>>>>> + spinlock_t phyid_map_lock; >>>>>> + struct kvm_phyid_map *phyid_map; >>>>>> >>>>>> s64 time_offset; >>>>>> struct kvm_context __percpu *vmcs; >>>>>> diff --git a/arch/loongarch/include/asm/kvm_vcpu.h b/arch/loongarch/include/asm/kvm_vcpu.h >>>>>> index 0cb4fdb8a9b5..9f53950959da 100644 >>>>>> --- a/arch/loongarch/include/asm/kvm_vcpu.h >>>>>> +++ b/arch/loongarch/include/asm/kvm_vcpu.h >>>>>> @@ -81,6 +81,7 @@ void kvm_save_timer(struct kvm_vcpu *vcpu); >>>>>> void kvm_restore_timer(struct kvm_vcpu *vcpu); >>>>>> >>>>>> int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq); >>>>>> +struct kvm_vcpu *kvm_get_vcpu_by_cpuid(struct kvm *kvm, int cpuid); >>>>>> >>>>>> /* >>>>>> * Loongarch KVM guest interrupt handling >>>>>> diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c >>>>>> index 3a8779065f73..b633fd28b8db 100644 >>>>>> --- a/arch/loongarch/kvm/vcpu.c >>>>>> +++ b/arch/loongarch/kvm/vcpu.c >>>>>> @@ -274,6 +274,95 @@ static int _kvm_getcsr(struct kvm_vcpu *vcpu, unsigned int id, u64 *val) >>>>>> return 0; >>>>>> } >>>>>> >>>>>> +static inline int kvm_set_cpuid(struct kvm_vcpu *vcpu, u64 val) >>>>>> +{ >>>>>> + int cpuid; >>>>>> + struct loongarch_csrs *csr = vcpu->arch.csr; >>>>>> + struct kvm_phyid_map *map; >>>>>> + >>>>>> + if (val >= KVM_MAX_PHYID) >>>>>> + return -EINVAL; >>>>>> + >>>>>> + cpuid = kvm_read_sw_gcsr(csr, LOONGARCH_CSR_ESTAT); >>>>>> + map = vcpu->kvm->arch.phyid_map; >>>>>> + spin_lock(&vcpu->kvm->arch.phyid_map_lock); >>>>>> + if (map->phys_map[cpuid].enabled) { >>>>>> + /* >>>>>> + * Cpuid is already set before >>>>>> + * Forbid changing different cpuid at runtime >>>>>> + */ >>>>>> + if (cpuid != val) { >>>>>> + /* >>>>>> + * Cpuid 0 is initial value for vcpu, maybe invalid >>>>>> + * unset value for vcpu >>>>>> + */ >>>>>> + if (cpuid) { >>>>>> + spin_unlock(&vcpu->kvm->arch.phyid_map_lock); >>>>>> + return -EINVAL; >>>>>> + } >>>>>> + } else { >>>>>> + /* Discard duplicated cpuid set */ >>>>>> + spin_unlock(&vcpu->kvm->arch.phyid_map_lock); >>>>>> + return 0; >>>>>> + } >>>>>> + } >>>>> I have changed the logic and comments when I apply, you can double >>>>> check whether it is correct. >>>> I checkout the latest version, the modification in function >>>> kvm_set_cpuid() is good for me. >>> Now the modified version is like this: >>> >>> + if (map->phys_map[cpuid].enabled) { >>> + /* Discard duplicated CPUID set operation */ >>> + if (cpuid == val) { >>> + spin_unlock(&vcpu->kvm->arch.phyid_map_lock); >>> + return 0; >>> + } >>> + >>> + /* >>> + * CPUID is already set before >>> + * Forbid changing different CPUID at runtime >>> + * But CPUID 0 is the initial value for vcpu, so allow >>> + * changing from 0 to others >>> + */ >>> + if (cpuid) { >>> + spin_unlock(&vcpu->kvm->arch.phyid_map_lock); >>> + return -EINVAL; >>> + } >>> + } >>> But I still doubt whether we should allow changing from 0 to others >>> while map->phys_map[cpuid].enabled is 1. >> It is necessary since the default sw cpuid is zero :-( And we can >> optimize it in later, such as set INVALID cpuid in function >> kvm_arch_vcpu_create() and logic will be simple in function kvm_set_cpuid(). > In my opinion, if a vcpu with a uninitialized default physid=0, then > map->phys_map[cpuid].enabled should be 0, then code won't come here. > And if a vcpu with a real physid=0, then map->phys_map[cpuid].enabled > is 1, but we shouldn't allow it to change physid in this case. yes, that is actually a problem. vcpu0 firstly set physid=0, and vcpu0 set physid=1 again is not allowed. vcpu0 firstly set physid=0, and vcpu1 set physid=1 is allowed. > > Huacai > >> >> Regards >> Bibo Mao >> >>> >>> Huacai >>> >>>>> >>>>>> + >>>>>> + if (map->phys_map[val].enabled) { >>>>>> + /* >>>>>> + * New cpuid is already set with other vcpu >>>>>> + * Forbid sharing the same cpuid between different vcpus >>>>>> + */ >>>>>> + if (map->phys_map[val].vcpu != vcpu) { >>>>>> + spin_unlock(&vcpu->kvm->arch.phyid_map_lock); >>>>>> + return -EINVAL; >>>>>> + } >>>>>> + >>>>>> + /* Discard duplicated cpuid set operation*/ >>>>>> + spin_unlock(&vcpu->kvm->arch.phyid_map_lock); >>>>>> + return 0; >>>>>> + } >>>>>> + >>>>>> + kvm_write_sw_gcsr(csr, LOONGARCH_CSR_CPUID, val); >>>>>> + map->phys_map[val].enabled = true; >>>>>> + map->phys_map[val].vcpu = vcpu; >>>>>> + if (map->max_phyid < val) >>>>>> + map->max_phyid = val; >>>>>> + spin_unlock(&vcpu->kvm->arch.phyid_map_lock); >>>>>> + return 0; >>>>>> +} >>>>>> + >>>>>> +struct kvm_vcpu *kvm_get_vcpu_by_cpuid(struct kvm *kvm, int cpuid) >>>>>> +{ >>>>>> + struct kvm_phyid_map *map; >>>>>> + >>>>>> + if (cpuid >= KVM_MAX_PHYID) >>>>>> + return NULL; >>>>>> + >>>>>> + map = kvm->arch.phyid_map; >>>>>> + if (map->phys_map[cpuid].enabled) >>>>>> + return map->phys_map[cpuid].vcpu; >>>>>> + >>>>>> + return NULL; >>>>>> +} >>>>>> + >>>>>> +static inline void kvm_drop_cpuid(struct kvm_vcpu *vcpu) >>>>>> +{ >>>>>> + int cpuid; >>>>>> + struct loongarch_csrs *csr = vcpu->arch.csr; >>>>>> + struct kvm_phyid_map *map; >>>>>> + >>>>>> + map = vcpu->kvm->arch.phyid_map; >>>>>> + cpuid = kvm_read_sw_gcsr(csr, LOONGARCH_CSR_ESTAT); >>>>>> + if (cpuid >= KVM_MAX_PHYID) >>>>>> + return; >>>>>> + >>>>>> + if (map->phys_map[cpuid].enabled) { >>>>>> + map->phys_map[cpuid].vcpu = NULL; >>>>>> + map->phys_map[cpuid].enabled = false; >>>>>> + kvm_write_sw_gcsr(csr, LOONGARCH_CSR_CPUID, 0); >>>>>> + } >>>>>> +} >>>>> While kvm_set_cpuid() is protected by a spinlock, do kvm_drop_cpuid() >>>>> and kvm_get_vcpu_by_cpuid() also need it? >>>>> >>>> It is good to me that spinlock is added in function kvm_drop_cpuid(). >>>> And thinks for the efforts. >>>> >>>> Regards >>>> Bibo Mao >>>>>> + >>>>>> static int _kvm_setcsr(struct kvm_vcpu *vcpu, unsigned int id, u64 val) >>>>>> { >>>>>> int ret = 0, gintc; >>>>>> @@ -291,7 +380,8 @@ static int _kvm_setcsr(struct kvm_vcpu *vcpu, unsigned int id, u64 val) >>>>>> kvm_set_sw_gcsr(csr, LOONGARCH_CSR_ESTAT, gintc); >>>>>> >>>>>> return ret; >>>>>> - } >>>>>> + } else if (id == LOONGARCH_CSR_CPUID) >>>>>> + return kvm_set_cpuid(vcpu, val); >>>>>> >>>>>> kvm_write_sw_gcsr(csr, id, val); >>>>>> >>>>>> @@ -943,6 +1033,7 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu) >>>>>> hrtimer_cancel(&vcpu->arch.swtimer); >>>>>> kvm_mmu_free_memory_cache(&vcpu->arch.mmu_page_cache); >>>>>> kfree(vcpu->arch.csr); >>>>>> + kvm_drop_cpuid(vcpu); >>>>> I think this line should be before the above kfree(), otherwise you >>>>> get a "use after free". >>>>> >>>>> Huacai >>>>> >>>>>> >>>>>> /* >>>>>> * If the vCPU is freed and reused as another vCPU, we don't want the >>>>>> diff --git a/arch/loongarch/kvm/vm.c b/arch/loongarch/kvm/vm.c >>>>>> index 0a37f6fa8f2d..6006a28653ad 100644 >>>>>> --- a/arch/loongarch/kvm/vm.c >>>>>> +++ b/arch/loongarch/kvm/vm.c >>>>>> @@ -30,6 +30,14 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) >>>>>> if (!kvm->arch.pgd) >>>>>> return -ENOMEM; >>>>>> >>>>>> + kvm->arch.phyid_map = kvzalloc(sizeof(struct kvm_phyid_map), >>>>>> + GFP_KERNEL_ACCOUNT); >>>>>> + if (!kvm->arch.phyid_map) { >>>>>> + free_page((unsigned long)kvm->arch.pgd); >>>>>> + kvm->arch.pgd = NULL; >>>>>> + return -ENOMEM; >>>>>> + } >>>>>> + >>>>>> kvm_init_vmcs(kvm); >>>>>> kvm->arch.gpa_size = BIT(cpu_vabits - 1); >>>>>> kvm->arch.root_level = CONFIG_PGTABLE_LEVELS - 1; >>>>>> @@ -44,6 +52,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) >>>>>> for (i = 0; i <= kvm->arch.root_level; i++) >>>>>> kvm->arch.pte_shifts[i] = PAGE_SHIFT + i * (PAGE_SHIFT - 3); >>>>>> >>>>>> + spin_lock_init(&kvm->arch.phyid_map_lock); >>>>>> return 0; >>>>>> } >>>>>> >>>>>> @@ -51,7 +60,9 @@ void kvm_arch_destroy_vm(struct kvm *kvm) >>>>>> { >>>>>> kvm_destroy_vcpus(kvm); >>>>>> free_page((unsigned long)kvm->arch.pgd); >>>>>> + kvfree(kvm->arch.phyid_map); >>>>>> kvm->arch.pgd = NULL; >>>>>> + kvm->arch.phyid_map = NULL; >>>>>> } >>>>>> >>>>>> int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) >>>>>> -- >>>>>> 2.39.3 >>>>>> >>>> >>