Received: by 2002:a05:6a10:5bc5:0:0:0:0 with SMTP id os5csp399612pxb; Tue, 19 Oct 2021 05:19:33 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzyXsUhCFIg1ZA1HIWex6ZYjcLsu9IO3uE1aHmwycQmXfqrgFNZx8gF9dUWT2tOr5cp40Rv X-Received: by 2002:aa7:c956:: with SMTP id h22mr12655746edt.24.1634645973505; Tue, 19 Oct 2021 05:19:33 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1634645973; cv=none; d=google.com; s=arc-20160816; b=CHyLCbinAE5csu5Mt3Y6xGqBl7CuutEAGB7fYOVcjws9TnVGoTIJJ7WzNXsJdQEzRY MxBj5qtn1OWW21vkfJ4cRpd4qSFSwMbDbJOqPOzpkuTcF33J9u4BHJ5O1DwBPC6bg88Q 3slC/qfi5XJnFeCyyU1WK4SjkWjMrgNT30wC9/j6n7h+hANGMZ/JSsOsLzLumnJITEOT H5DXfsrlY48OKF+8Ij/gtK0Hxm5Cbf5t4DFP2zfcbDTsa+0EmIiP2NNOFGfz8gmfhzZh lPcPYUbKSilHUnWlDn6ZdpHyn3pbFxcLB4VnK2OPb80/5bqqtrpL76i8Bc6McZKjvohh rZ/w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:from:subject:references:mime-version :message-id:in-reply-to:date:dkim-signature; bh=VqYPavyR2JRTUWvE5kjjzlUp50pAuHmuHcARAYk4cwk=; b=Zo1Uv6jXzojtvs5aiNfhRm398kHDQaI2qJKsRBUSf6YlBkW/HpQFbSl8RoTVEHQehy 6lGMJ0NMz+nHytqe8MJUCATptYMylQTMYxvv4n2tS6VvBitmr9ifi60kmcGV46yQYWOo siQeVGpCrIMJNpZuBCMHd8J3CsfgXlGqm95peXSvHR+lQwZzK7uaisTTihk5l4QbgCJD HFCO4ToZs6jEIXNSv6yhVIjiztvNLR7M7tCCVHddspwCry1ObMiwypD6GuTT5DtOs1NP GheZMqsHfGpmPxe1f3EzZCbtP1XSIoi4TeLm+PgJjWBGqM8D34k8RTSK8xxuXsTEP10l hG+w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b=fGi7IVyH; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id j8si23475343ejk.456.2021.10.19.05.19.09; Tue, 19 Oct 2021 05:19:33 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b=fGi7IVyH; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235771AbhJSMQH (ORCPT + 99 others); Tue, 19 Oct 2021 08:16:07 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33370 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235671AbhJSMPz (ORCPT ); Tue, 19 Oct 2021 08:15:55 -0400 Received: from mail-wr1-x449.google.com (mail-wr1-x449.google.com [IPv6:2a00:1450:4864:20::449]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 257B8C061745 for ; Tue, 19 Oct 2021 05:13:43 -0700 (PDT) Received: by mail-wr1-x449.google.com with SMTP id d13-20020adfa34d000000b00160aa1cc5f1so10069709wrb.14 for ; Tue, 19 Oct 2021 05:13:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=VqYPavyR2JRTUWvE5kjjzlUp50pAuHmuHcARAYk4cwk=; b=fGi7IVyHWwfKQS2WbRt2o+yRVdxkv/7OeCdfA8Py2fFF0DRYQaLM7bUAn4tRvOCb6L UYC9SRTQ42xvB8Xoqub8ks9s52dpmbfkm+nh04FUXNyyBbLGkbdTtw3MW8S/ct0VuF1a hatlEFd42G71G8EgIcsabJ2RwHJb+puTGYm+uiRBCH5+mK8nCmY59E2VMpa+tfRufGpu Uyux/TC1Du3dMEK8gNu4keJ5UFr673qhIq57qoEayFQBYpe7vg6F+mJBhZHawxAHDBcN If1bGrUtd8wJRrN6RNtohM6Jmv2jaGMrZ/5+CnlgLSAkSU8VUMwN/vtvLWctXfMQ/0jH T5Jw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=VqYPavyR2JRTUWvE5kjjzlUp50pAuHmuHcARAYk4cwk=; b=b0f0vF8/iD5tDnlG+HqTrGZ2gPAQH5+Fl24eU2tV3qZTJ8g3zpo69x8BhPIudBoMzz DOv8h19NUneXq6Vjv01UyPMygNBBtYSkcs/Ci9WV91WsrpVgYcz1TRAhjEQbSSNT+Oy1 TciakE6FUMND08VxwkvrfDCYtuILot80GA54QToveM5ncN55760vOOC9I+SN8P51kLW4 9+clI5qG5zNcG0E/sUj4Hk6WD+NE7qT40UR1RCnuf2fDozl48AFwK8ChK+sDjzxndeKY Xd6VwJoOZjkgPcCSne5zJkwwaZriS1klDqLWhNb4LZ/dX1S5+0mUCrmsgmCAnEniNLA6 KcEQ== X-Gm-Message-State: AOAM533sA1j4D4wOdYnFvO8HSh2dDnz8qdexga5HrXzG85YeO7LMTvVz vXYnarPRfNOmkEZiDA3JrrbD1QZLfrKz X-Received: from luke.lon.corp.google.com ([2a00:79e0:d:210:59ca:401f:83a8:de6d]) (user=qperret job=sendgmr) by 2002:a05:600c:4e94:: with SMTP id f20mr5727676wmq.52.1634645621773; Tue, 19 Oct 2021 05:13:41 -0700 (PDT) Date: Tue, 19 Oct 2021 13:13:04 +0100 In-Reply-To: <20211019121304.2732332-1-qperret@google.com> Message-Id: <20211019121304.2732332-16-qperret@google.com> Mime-Version: 1.0 References: <20211019121304.2732332-1-qperret@google.com> X-Mailer: git-send-email 2.33.0.1079.g6e70778dc9-goog Subject: [PATCH v2 15/15] KVM: arm64: pkvm: Unshare guest structs during teardown From: Quentin Perret To: Marc Zyngier , James Morse , Alexandru Elisei , Suzuki K Poulose , Catalin Marinas , Will Deacon , Fuad Tabba , David Brazdil , Andrew Walbran Cc: linux-arm-kernel@lists.infradead.org, kvmarm@lists.cs.columbia.edu, linux-kernel@vger.kernel.org, kernel-team@android.com, qperret@google.com Content-Type: text/plain; charset="UTF-8" Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Make use of the newly introduced unshare hypercall during guest teardown to unmap guest-related data structures from the hyp stage-1. Signed-off-by: Quentin Perret --- arch/arm64/include/asm/kvm_host.h | 2 ++ arch/arm64/include/asm/kvm_mmu.h | 1 + arch/arm64/kvm/arm.c | 2 ++ arch/arm64/kvm/fpsimd.c | 29 +++++++++++++++++++++ arch/arm64/kvm/mmu.c | 42 +++++++++++++++++++++++++++++++ arch/arm64/kvm/reset.c | 8 +++++- 6 files changed, 83 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index d1451c8a768b..9f70e82c7436 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -323,6 +323,7 @@ struct kvm_vcpu_arch { struct thread_info *host_thread_info; /* hyp VA */ struct user_fpsimd_state *host_fpsimd_state; /* hyp VA */ + struct task_struct *parent_task; struct { /* {Break,watch}point registers */ @@ -738,6 +739,7 @@ int kvm_arch_vcpu_run_map_fp(struct kvm_vcpu *vcpu); void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu); void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu); void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu); +void kvm_vcpu_unshare_task_fp(struct kvm_vcpu *vcpu); static inline bool kvm_pmu_counter_deferred(struct perf_event_attr *attr) { diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h index 185d0f62b724..81839e9a8a24 100644 --- a/arch/arm64/include/asm/kvm_mmu.h +++ b/arch/arm64/include/asm/kvm_mmu.h @@ -151,6 +151,7 @@ static __always_inline unsigned long __kern_hyp_va(unsigned long v) #include int kvm_share_hyp(void *from, void *to); +void kvm_unshare_hyp(void *from, void *to); int create_hyp_mappings(void *from, void *to, enum kvm_pgtable_prot prot); int create_hyp_io_mappings(phys_addr_t phys_addr, size_t size, void __iomem **kaddr, diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index 5312d5a2ef69..ebab9529b736 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -188,6 +188,8 @@ void kvm_arch_destroy_vm(struct kvm *kvm) } } atomic_set(&kvm->online_vcpus, 0); + + kvm_unshare_hyp(kvm, kvm + 1); } int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c index 2fe1128d9f3d..ace5ebef8aab 100644 --- a/arch/arm64/kvm/fpsimd.c +++ b/arch/arm64/kvm/fpsimd.c @@ -15,6 +15,22 @@ #include #include +void kvm_vcpu_unshare_task_fp(struct kvm_vcpu *vcpu) +{ + struct task_struct *p = vcpu->arch.parent_task; + struct user_fpsimd_state *fpsimd; + struct thread_info *ti; + + if (!is_protected_kvm_enabled() || !p) + return; + + ti = &p->thread_info; + kvm_unshare_hyp(ti, ti + 1); + fpsimd = &p->thread.uw.fpsimd_state; + kvm_unshare_hyp(fpsimd, fpsimd + 1); + put_task_struct(p); +} + /* * Called on entry to KVM_RUN unless this vcpu previously ran at least * once and the most recent prior KVM_RUN for this vcpu was called from @@ -31,6 +47,8 @@ int kvm_arch_vcpu_run_map_fp(struct kvm_vcpu *vcpu) struct thread_info *ti = ¤t->thread_info; struct user_fpsimd_state *fpsimd = ¤t->thread.uw.fpsimd_state; + kvm_vcpu_unshare_task_fp(vcpu); + /* * Make sure the host task thread flags and fpsimd state are * visible to hyp: @@ -45,6 +63,17 @@ int kvm_arch_vcpu_run_map_fp(struct kvm_vcpu *vcpu) vcpu->arch.host_thread_info = kern_hyp_va(ti); vcpu->arch.host_fpsimd_state = kern_hyp_va(fpsimd); + + /* + * We need to keep current's task_struct pinned until its data has been + * unshared with the hypervisor to make sure it is not re-used by the + * kernel and donated to someone else while already shared -- see + * kvm_vcpu_unshare_task_fp() for the matching put_task_struct(). + */ + if (is_protected_kvm_enabled()) { + get_task_struct(current); + vcpu->arch.parent_task = current; + } error: return ret; } diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c index f0c16ed95974..d548141da2ea 100644 --- a/arch/arm64/kvm/mmu.c +++ b/arch/arm64/kvm/mmu.c @@ -344,6 +344,32 @@ static int share_pfn_hyp(u64 pfn) return ret; } +static int unshare_pfn_hyp(u64 pfn) +{ + struct rb_node **node, *parent; + struct hyp_shared_pfn *this; + int ret = 0; + + mutex_lock(&hyp_shared_pfns_lock); + this = find_shared_pfn(pfn, &node, &parent); + if (WARN_ON(!this)) { + ret = -EINVAL; + goto unlock; + } + + this->count--; + if (this->count) + goto unlock; + + rb_erase(&this->node, &hyp_shared_pfns); + kfree(this); + ret = kvm_call_hyp_nvhe(__pkvm_host_unshare_hyp, pfn, 1); +unlock: + mutex_unlock(&hyp_shared_pfns_lock); + + return ret; +} + int kvm_share_hyp(void *from, void *to) { phys_addr_t start, end, cur; @@ -368,6 +394,22 @@ int kvm_share_hyp(void *from, void *to) return 0; } +void kvm_unshare_hyp(void *from, void *to) +{ + phys_addr_t start, end, cur; + u64 pfn; + + if (is_kernel_in_hyp_mode() || kvm_host_owns_hyp_mappings() || !from) + return; + + start = ALIGN_DOWN(kvm_kaddr_to_phys(from), PAGE_SIZE); + end = PAGE_ALIGN(kvm_kaddr_to_phys(to)); + for (cur = start; cur < end; cur += PAGE_SIZE) { + pfn = __phys_to_pfn(cur); + WARN_ON(unshare_pfn_hyp(pfn)); + } +} + /** * create_hyp_mappings - duplicate a kernel virtual address range in Hyp mode * @from: The virtual kernel start address of the range diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index cf781ec9212a..bf15e9de4123 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c @@ -150,7 +150,13 @@ bool kvm_arm_vcpu_is_finalized(struct kvm_vcpu *vcpu) void kvm_arm_vcpu_destroy(struct kvm_vcpu *vcpu) { - kfree(vcpu->arch.sve_state); + void *sve_state = vcpu->arch.sve_state; + + kvm_vcpu_unshare_task_fp(vcpu); + kvm_unshare_hyp(vcpu, vcpu + 1); + if (sve_state) + kvm_unshare_hyp(sve_state, sve_state + vcpu_sve_state_size(vcpu)); + kfree(sve_state); } static void kvm_vcpu_reset_sve(struct kvm_vcpu *vcpu) -- 2.33.0.1079.g6e70778dc9-goog