From nobody Fri Dec 19 14:35:39 2025 Received: from mail-wm1-f74.google.com (mail-wm1-f74.google.com [209.85.128.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3D18B266EFC for ; Tue, 20 May 2025 08:53:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747731189; cv=none; b=LLv4z5WITh1Jr0NHNL6PyDhfoKIkP89KvlkVXxXMLLnMXXHutXb40n33c4B0c9/k4kYxQDn86iXz47s3Oyg6+U1uO3MiJUyqxYSWVwphX2CoNFq1sA8151gkX9Hw5SeqZrn1SOLCoiiY9+HjsDUR3eZoHnqyEBeSFnl/MVE+V5g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747731189; c=relaxed/simple; bh=Zt7ydWx9TCoC9zKBk9lU0ZLLLpcHQ63JPO77QNtkQRQ=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=ATERi9dtXoR6jPg4mZb/ZDOBVWxZqk8bNpSMRjEMdiB1m5jrJRx1GdRlnZPAuBwNZKKMdVnh97S997zchlWE1k1imGP0cjcf+8cSVL342qQnZF1+thFL0wO+KGQEWSIIEI6AOHDC6j2yynZUIhuEYXNjZ1kNyeUZYakJ4CbGfx8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--vdonnefort.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=0s43ZvEt; arc=none smtp.client-ip=209.85.128.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--vdonnefort.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="0s43ZvEt" Received: by mail-wm1-f74.google.com with SMTP id 5b1f17b1804b1-441c96c1977so37061955e9.0 for ; Tue, 20 May 2025 01:53:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1747731185; x=1748335985; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=8eV/b8y5mk2obyefKPJMTlOdN01tVjbRhdILiqDQGZo=; b=0s43ZvEt43NXs1nQado3uY05S7FPYVVMM6v5bsv1Q8mm0ymI5P66ahaZPO2UuLesKj gtiGJBb//DWMWwrqe5Ybd5Gcb39FFlJV3qQ7O/YZbFK+VcThZmwoHv0uw6NBtFJasLxU PTCw/Qpfi2i8aNgyfKZvCmmVQu3QQuLdO5PkLYFiEUbDTYzbDZokbmBYyy7s02FPJtg1 SMFLD9AR/JuzEzpOxHSCrb+kap+1nq8b4SpoqHMN/amPnQjXygtlmbROOpBW1CVldMZE /yBppe0u+/4JPC9A4eYpGl9iNmieTwPSN+BPcDKEoAhhxDwPTqQGjDBg6P1Q9IZ422Ze g4+Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1747731185; x=1748335985; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=8eV/b8y5mk2obyefKPJMTlOdN01tVjbRhdILiqDQGZo=; b=pSDXbQ09quUhtY/sCOTbBOZ2dlt2U9k7gdm4q5UgM2S7bpsIusLxVRdDDE9OI0DfhX 2zJALeEd0VAdfHTgbBqjxxZesHgBWygE7EngoqlUOBXRSYmueitWRz7DwJPRnxFRNpIA QsN7dmjIUdkD1EuS4PQ/FgEQdxgP+O11jhP7yAe0Kf9h92iPrlDvpoaaToqID2NBe15U zjPMf/AHhbP5UQFQ9b5CyRCIQtQnFXwvsMAE6A6wIf0UZ4cyN98c/eSDydQ/MEsZ3t8y Hq95BX9MSgPlKOM3Vc45jNfhl0vFIvUlFMI2XB3bFBmn6MXubGbEPyLNxDHm4Y03TwPz JapA== X-Forwarded-Encrypted: i=1; AJvYcCX5EIxUEJzKK+zlkTilSoSLuU3OgMusAB45Z4TZfx/5mXTIuWnnma0dtBsMIxEc75VT8wGU9NiKs2LtZ1k=@vger.kernel.org X-Gm-Message-State: AOJu0YzHH7UDCBfB3DNbFzyz9SW0tttUZPFKAnIeLM3+o5pVacWeHwcX vFgk/VR1J2PZMov0pTJqJawfTcg9WL+gD8XUZ2fK7Sk4YAh3Z3n0ebqjx7kSZfEhJsXhps+1vm4 KAa6Po8LG0Ao1miMKmbIhEQ== X-Google-Smtp-Source: AGHT+IGNQClPtb39kNDrZ/LoRUA+zgeQ/ywPgjx7YyU7q28JnkGlV8/zAlfQAZoYxyadZaqXQgpd/gTa3iD3bses X-Received: from wmrn15.prod.google.com ([2002:a05:600c:500f:b0:442:ea0c:c453]) (user=vdonnefort job=prod-delivery.src-stubby-dispatcher) by 2002:a05:600c:548d:b0:439:9424:1b70 with SMTP id 5b1f17b1804b1-442ff03c228mr142671705e9.30.1747731185777; Tue, 20 May 2025 01:53:05 -0700 (PDT) Date: Tue, 20 May 2025 09:51:54 +0100 In-Reply-To: <20250520085201.3059786-1-vdonnefort@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250520085201.3059786-1-vdonnefort@google.com> X-Mailer: git-send-email 2.49.0.1143.g0be31eac6b-goog Message-ID: <20250520085201.3059786-4-vdonnefort@google.com> Subject: [PATCH v5 03/10] KVM: arm64: Add a range to __pkvm_host_share_guest() From: Vincent Donnefort To: maz@kernel.org, oliver.upton@linux.dev, joey.gouly@arm.com, suzuki.poulose@arm.com, yuzenghui@huawei.com, catalin.marinas@arm.com, will@kernel.org Cc: qperret@google.com, linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org, kernel-team@android.com, Vincent Donnefort Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" In preparation for supporting stage-2 huge mappings for np-guest. Add a nr_pages argument to the __pkvm_host_share_guest hypercall. This range supports only two values: 1 or PMD_SIZE / PAGE_SIZE (that is 512 on a 4K-pages system). Signed-off-by: Vincent Donnefort diff --git a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h b/arch/arm64/kvm= /hyp/include/nvhe/mem_protect.h index 26016eb9323f..47aa7b01114f 100644 --- a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h +++ b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h @@ -39,7 +39,7 @@ int __pkvm_host_donate_hyp(u64 pfn, u64 nr_pages); int __pkvm_hyp_donate_host(u64 pfn, u64 nr_pages); int __pkvm_host_share_ffa(u64 pfn, u64 nr_pages); int __pkvm_host_unshare_ffa(u64 pfn, u64 nr_pages); -int __pkvm_host_share_guest(u64 pfn, u64 gfn, struct pkvm_hyp_vcpu *vcpu, +int __pkvm_host_share_guest(u64 pfn, u64 gfn, u64 nr_pages, struct pkvm_hy= p_vcpu *vcpu, enum kvm_pgtable_prot prot); int __pkvm_host_unshare_guest(u64 gfn, struct pkvm_hyp_vm *hyp_vm); int __pkvm_host_relax_perms_guest(u64 gfn, struct pkvm_hyp_vcpu *vcpu, enu= m kvm_pgtable_prot prot); diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/h= yp-main.c index 59db9606e6e1..4d3d215955c3 100644 --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c @@ -245,7 +245,8 @@ static void handle___pkvm_host_share_guest(struct kvm_c= pu_context *host_ctxt) { DECLARE_REG(u64, pfn, host_ctxt, 1); DECLARE_REG(u64, gfn, host_ctxt, 2); - DECLARE_REG(enum kvm_pgtable_prot, prot, host_ctxt, 3); + DECLARE_REG(u64, nr_pages, host_ctxt, 3); + DECLARE_REG(enum kvm_pgtable_prot, prot, host_ctxt, 4); struct pkvm_hyp_vcpu *hyp_vcpu; int ret =3D -EINVAL; =20 @@ -260,7 +261,7 @@ static void handle___pkvm_host_share_guest(struct kvm_c= pu_context *host_ctxt) if (ret) goto out; =20 - ret =3D __pkvm_host_share_guest(pfn, gfn, hyp_vcpu, prot); + ret =3D __pkvm_host_share_guest(pfn, gfn, nr_pages, hyp_vcpu, prot); out: cpu_reg(host_ctxt, 1) =3D ret; } diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvh= e/mem_protect.c index 1018a6f66359..8e0847aa090d 100644 --- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c +++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c @@ -695,10 +695,9 @@ static enum pkvm_page_state guest_get_page_state(kvm_p= te_t pte, u64 addr) return pkvm_getstate(kvm_pgtable_stage2_pte_prot(pte)); } =20 -static int __guest_check_page_state_range(struct pkvm_hyp_vcpu *vcpu, u64 = addr, +static int __guest_check_page_state_range(struct pkvm_hyp_vm *vm, u64 addr, u64 size, enum pkvm_page_state state) { - struct pkvm_hyp_vm *vm =3D pkvm_hyp_vcpu_to_hyp_vm(vcpu); struct check_walk_data d =3D { .desired =3D state, .get_page_state =3D guest_get_page_state, @@ -907,48 +906,72 @@ int __pkvm_host_unshare_ffa(u64 pfn, u64 nr_pages) return ret; } =20 -int __pkvm_host_share_guest(u64 pfn, u64 gfn, struct pkvm_hyp_vcpu *vcpu, +static int __guest_check_transition_size(u64 phys, u64 ipa, u64 nr_pages, = u64 *size) +{ + if (nr_pages =3D=3D 1) { + *size =3D PAGE_SIZE; + return 0; + } + + return -EINVAL; +} + +int __pkvm_host_share_guest(u64 pfn, u64 gfn, u64 nr_pages, struct pkvm_hy= p_vcpu *vcpu, enum kvm_pgtable_prot prot) { struct pkvm_hyp_vm *vm =3D pkvm_hyp_vcpu_to_hyp_vm(vcpu); u64 phys =3D hyp_pfn_to_phys(pfn); u64 ipa =3D hyp_pfn_to_phys(gfn); - struct hyp_page *page; + u64 size; int ret; =20 if (prot & ~KVM_PGTABLE_PROT_RWX) return -EINVAL; =20 - ret =3D check_range_allowed_memory(phys, phys + PAGE_SIZE); + ret =3D __guest_check_transition_size(phys, ipa, nr_pages, &size); + if (ret) + return ret; + + ret =3D check_range_allowed_memory(phys, phys + size); if (ret) return ret; =20 host_lock_component(); guest_lock_component(vm); =20 - ret =3D __guest_check_page_state_range(vcpu, ipa, PAGE_SIZE, PKVM_NOPAGE); + ret =3D __guest_check_page_state_range(vm, ipa, size, PKVM_NOPAGE); if (ret) goto unlock; =20 - page =3D hyp_phys_to_page(phys); - switch (get_host_state(page)) { - case PKVM_PAGE_OWNED: - WARN_ON(__host_set_page_state_range(phys, PAGE_SIZE, PKVM_PAGE_SHARED_OW= NED)); - break; - case PKVM_PAGE_SHARED_OWNED: - if (page->host_share_guest_count) - break; - /* Only host to np-guest multi-sharing is tolerated */ - fallthrough; - default: - ret =3D -EPERM; - goto unlock; + for_each_hyp_page(page, phys, size) { + switch (get_host_state(page)) { + case PKVM_PAGE_OWNED: + continue; + case PKVM_PAGE_SHARED_OWNED: + if (page->host_share_guest_count =3D=3D U32_MAX) { + ret =3D -EBUSY; + goto unlock; + } + + /* Only host to np-guest multi-sharing is tolerated */ + if (page->host_share_guest_count) + continue; + + fallthrough; + default: + ret =3D -EPERM; + goto unlock; + } } =20 - WARN_ON(kvm_pgtable_stage2_map(&vm->pgt, ipa, PAGE_SIZE, phys, + for_each_hyp_page(page, phys, size) { + set_host_state(page, PKVM_PAGE_SHARED_OWNED); + page->host_share_guest_count++; + } + + WARN_ON(kvm_pgtable_stage2_map(&vm->pgt, ipa, size, phys, pkvm_mkstate(prot, PKVM_PAGE_SHARED_BORROWED), &vcpu->vcpu.arch.pkvm_memcache, 0)); - page->host_share_guest_count++; =20 unlock: guest_unlock_component(vm); @@ -1169,6 +1192,9 @@ static void assert_page_state(void) struct pkvm_hyp_vcpu *vcpu =3D &selftest_vcpu; u64 phys =3D hyp_virt_to_phys(virt); u64 ipa[2] =3D { selftest_ipa(), selftest_ipa() + PAGE_SIZE }; + struct pkvm_hyp_vm *vm; + + vm =3D pkvm_hyp_vcpu_to_hyp_vm(vcpu); =20 host_lock_component(); WARN_ON(__host_check_page_state_range(phys, size, selftest_state.host)); @@ -1179,8 +1205,8 @@ static void assert_page_state(void) hyp_unlock_component(); =20 guest_lock_component(&selftest_vm); - WARN_ON(__guest_check_page_state_range(vcpu, ipa[0], size, selftest_state= .guest[0])); - WARN_ON(__guest_check_page_state_range(vcpu, ipa[1], size, selftest_state= .guest[1])); + WARN_ON(__guest_check_page_state_range(vm, ipa[0], size, selftest_state.g= uest[0])); + WARN_ON(__guest_check_page_state_range(vm, ipa[1], size, selftest_state.g= uest[1])); guest_unlock_component(&selftest_vm); } =20 @@ -1218,7 +1244,7 @@ void pkvm_ownership_selftest(void *base) assert_transition_res(-EPERM, __pkvm_host_share_ffa, pfn, 1); assert_transition_res(-EPERM, __pkvm_host_unshare_ffa, pfn, 1); assert_transition_res(-EPERM, hyp_pin_shared_mem, virt, virt + size); - assert_transition_res(-EPERM, __pkvm_host_share_guest, pfn, gfn, vcpu, pr= ot); + assert_transition_res(-EPERM, __pkvm_host_share_guest, pfn, gfn, 1, vcpu,= prot); assert_transition_res(-ENOENT, __pkvm_host_unshare_guest, gfn, vm); =20 selftest_state.host =3D PKVM_PAGE_OWNED; @@ -1237,7 +1263,7 @@ void pkvm_ownership_selftest(void *base) assert_transition_res(-EPERM, __pkvm_host_donate_hyp, pfn, 1); assert_transition_res(-EPERM, __pkvm_host_share_ffa, pfn, 1); assert_transition_res(-EPERM, __pkvm_hyp_donate_host, pfn, 1); - assert_transition_res(-EPERM, __pkvm_host_share_guest, pfn, gfn, vcpu, pr= ot); + assert_transition_res(-EPERM, __pkvm_host_share_guest, pfn, gfn, 1, vcpu,= prot); assert_transition_res(-ENOENT, __pkvm_host_unshare_guest, gfn, vm); =20 assert_transition_res(0, hyp_pin_shared_mem, virt, virt + size); @@ -1249,7 +1275,7 @@ void pkvm_ownership_selftest(void *base) assert_transition_res(-EPERM, __pkvm_host_donate_hyp, pfn, 1); assert_transition_res(-EPERM, __pkvm_host_share_ffa, pfn, 1); assert_transition_res(-EPERM, __pkvm_hyp_donate_host, pfn, 1); - assert_transition_res(-EPERM, __pkvm_host_share_guest, pfn, gfn, vcpu, pr= ot); + assert_transition_res(-EPERM, __pkvm_host_share_guest, pfn, gfn, 1, vcpu,= prot); assert_transition_res(-ENOENT, __pkvm_host_unshare_guest, gfn, vm); =20 hyp_unpin_shared_mem(virt, virt + size); @@ -1268,7 +1294,7 @@ void pkvm_ownership_selftest(void *base) assert_transition_res(-EPERM, __pkvm_host_share_hyp, pfn); assert_transition_res(-EPERM, __pkvm_host_unshare_hyp, pfn); assert_transition_res(-EPERM, __pkvm_hyp_donate_host, pfn, 1); - assert_transition_res(-EPERM, __pkvm_host_share_guest, pfn, gfn, vcpu, pr= ot); + assert_transition_res(-EPERM, __pkvm_host_share_guest, pfn, gfn, 1, vcpu,= prot); assert_transition_res(-ENOENT, __pkvm_host_unshare_guest, gfn, vm); assert_transition_res(-EPERM, hyp_pin_shared_mem, virt, virt + size); =20 @@ -1279,8 +1305,8 @@ void pkvm_ownership_selftest(void *base) =20 selftest_state.host =3D PKVM_PAGE_SHARED_OWNED; selftest_state.guest[0] =3D PKVM_PAGE_SHARED_BORROWED; - assert_transition_res(0, __pkvm_host_share_guest, pfn, gfn, vcpu, prot); - assert_transition_res(-EPERM, __pkvm_host_share_guest, pfn, gfn, vcpu, pr= ot); + assert_transition_res(0, __pkvm_host_share_guest, pfn, gfn, 1, vcpu, prot= ); + assert_transition_res(-EPERM, __pkvm_host_share_guest, pfn, gfn, 1, vcpu,= prot); assert_transition_res(-EPERM, __pkvm_host_share_ffa, pfn, 1); assert_transition_res(-EPERM, __pkvm_host_donate_hyp, pfn, 1); assert_transition_res(-EPERM, __pkvm_host_share_hyp, pfn); @@ -1289,7 +1315,7 @@ void pkvm_ownership_selftest(void *base) assert_transition_res(-EPERM, hyp_pin_shared_mem, virt, virt + size); =20 selftest_state.guest[1] =3D PKVM_PAGE_SHARED_BORROWED; - assert_transition_res(0, __pkvm_host_share_guest, pfn, gfn + 1, vcpu, pro= t); + assert_transition_res(0, __pkvm_host_share_guest, pfn, gfn + 1, 1, vcpu, = prot); WARN_ON(hyp_virt_to_page(virt)->host_share_guest_count !=3D 2); =20 selftest_state.guest[0] =3D PKVM_NOPAGE; diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c index 83a737484046..0285e2cd2e7f 100644 --- a/arch/arm64/kvm/pkvm.c +++ b/arch/arm64/kvm/pkvm.c @@ -347,7 +347,7 @@ int pkvm_pgtable_stage2_map(struct kvm_pgtable *pgt, u6= 4 addr, u64 size, return -EINVAL; =20 lockdep_assert_held_write(&kvm->mmu_lock); - ret =3D kvm_call_hyp_nvhe(__pkvm_host_share_guest, pfn, gfn, prot); + ret =3D kvm_call_hyp_nvhe(__pkvm_host_share_guest, pfn, gfn, 1, prot); if (ret) { /* Is the gfn already mapped due to a racing vCPU? */ if (ret =3D=3D -EPERM) --=20 2.49.0.1143.g0be31eac6b-goog