From nobody Wed Oct 1 23:34:11 2025 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id BDD0B2F617F; Fri, 26 Sep 2025 11:03:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758884602; cv=none; b=KfOJ/dTfPuo7VN5MO551cryw3J836G6lKLyze9bK/kam9CMiYuCXp9hnDJZR812ZHBbdgzJIADxW0OOREkv6L+qGjMuWWH0/Em4DYJ9RVu+9g+lJbLgAVxk6Rrz9V1GmEfN8ieEiRHrkbKmqdMLjQlW+mSZbfbXo2KsoDfZ1YP4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758884602; c=relaxed/simple; bh=W5lM2Om5UZeLdIJDQW24L+lk68gNVW2qKZzpzg4jocM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=qnMGRFNYrKEZ0j1Y8VLrrA77bV+yapkrh3ccevGeExib41+Vzte7l/78WwWXI6qySpT+cZ2K5UEvpnkg7p2Cn4aQhqgngMy/7IQwZ5S3drz1fBdeFou/k8QsVVTN0YiXBuyMnVTxrQzHblYWl9rHCwVZc/WaGaLU2/M58dKHbbM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 48AC72BCC; Fri, 26 Sep 2025 04:03:12 -0700 (PDT) Received: from e122027.cambridge.arm.com (e122027.cambridge.arm.com [10.1.38.22]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id D58963F66E; Fri, 26 Sep 2025 04:03:16 -0700 (PDT) From: Steven Price To: kvm@vger.kernel.org, kvmarm@lists.linux.dev Cc: Catalin Marinas , Marc Zyngier , Will Deacon , Oliver Upton , Suzuki K Poulose , Zenghui Yu , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Joey Gouly , Fuad Tabba , linux-coco@lists.linux.dev, Ganapatrao Kulkarni , Gavin Shan , Shanker Donthineni , Alper Gun , "Aneesh Kumar K . V" , Emi Kisanuki , Vishal Annapurve , Steven Price Subject: [RFC PATCH 3/5] arm64: RME: Support RMI_EXIT_S2AP_CHANGE Date: Fri, 26 Sep 2025 12:02:52 +0100 Message-ID: <20250926110254.55449-4-steven.price@arm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250926110254.55449-1-steven.price@arm.com> References: <20250926110254.55449-1-steven.price@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" If the primary plane of a realm wishes to change the access permissions of memory for the other planes then this causes an exit to the normal world. KVM then must complete the request using RMI_RTT_SET_S2AP which may fail if there are missing RTTs. In this case KVM must allocate the missing RTTs and retry. Signed-off-by: Steven Price --- arch/arm64/include/asm/kvm_rme.h | 3 +++ arch/arm64/kvm/rme-exit.c | 27 +++++++++++++++++++++++++++ arch/arm64/kvm/rme.c | 25 +++++++++++++++++++++---- 3 files changed, 51 insertions(+), 4 deletions(-) diff --git a/arch/arm64/include/asm/kvm_rme.h b/arch/arm64/include/asm/kvm_= rme.h index e5c0c8274bf8..934b30a8e607 100644 --- a/arch/arm64/include/asm/kvm_rme.h +++ b/arch/arm64/include/asm/kvm_rme.h @@ -112,6 +112,9 @@ int kvm_rec_pre_enter(struct kvm_vcpu *vcpu); int handle_rec_exit(struct kvm_vcpu *vcpu, int rec_run_status); =20 int realm_aux_map(struct kvm_vcpu *vcpu, phys_addr_t ipa); +int kvm_realm_set_s2ap(struct kvm_vcpu *vcpu, + unsigned long start, + unsigned long end); =20 void kvm_realm_unmap_range(struct kvm *kvm, unsigned long ipa, diff --git a/arch/arm64/kvm/rme-exit.c b/arch/arm64/kvm/rme-exit.c index 04c8af8642af..b7e615f7b3a9 100644 --- a/arch/arm64/kvm/rme-exit.c +++ b/arch/arm64/kvm/rme-exit.c @@ -112,6 +112,31 @@ static int rec_exit_ripas_change(struct kvm_vcpu *vcpu) return -EFAULT; } =20 +static int rec_exit_s2ap_change(struct kvm_vcpu *vcpu) +{ + struct kvm *kvm =3D vcpu->kvm; + struct realm *realm =3D &kvm->arch.realm; + struct realm_rec *rec =3D &vcpu->arch.rec; + unsigned long base =3D rec->run->exit.s2ap_base; + unsigned long top =3D rec->run->exit.s2ap_top; + int ret =3D -EINVAL; + + if (kvm_realm_is_private_address(realm, base) && + kvm_realm_is_private_address(realm, top)) { + kvm_mmu_topup_memory_cache(&vcpu->arch.mmu_page_cache, + kvm_mmu_cache_min_pages(vcpu->arch.hw_mmu)); + write_lock(&kvm->mmu_lock); + ret =3D kvm_realm_set_s2ap(vcpu, base, top); + write_unlock(&kvm->mmu_lock); + } + + WARN_RATELIMIT(ret && ret !=3D -ENOMEM, + "Unable to satisfy SET_S2AP for %#lx - %#lx\n", + base, top); + + return 1; +} + static int rec_exit_host_call(struct kvm_vcpu *vcpu) { int i; @@ -192,6 +217,8 @@ int handle_rec_exit(struct kvm_vcpu *vcpu, int rec_run_= ret) return rec_exit_psci(vcpu); case RMI_EXIT_RIPAS_CHANGE: return rec_exit_ripas_change(vcpu); + case RMI_EXIT_S2AP_CHANGE: + return rec_exit_s2ap_change(vcpu); case RMI_EXIT_HOST_CALL: return rec_exit_host_call(vcpu); } diff --git a/arch/arm64/kvm/rme.c b/arch/arm64/kvm/rme.c index c420546d26f3..fa39a8393d53 100644 --- a/arch/arm64/kvm/rme.c +++ b/arch/arm64/kvm/rme.c @@ -1329,6 +1329,7 @@ static int kvm_populate_realm(struct kvm *kvm, enum ripas_action { RIPAS_INIT, RIPAS_SET, + SET_S2AP, }; =20 static int ripas_change(struct kvm *kvm, @@ -1348,12 +1349,13 @@ static int ripas_change(struct kvm *kvm, rec_phys =3D virt_to_phys(vcpu->arch.rec.rec_page); memcache =3D &vcpu->arch.mmu_page_cache; =20 - WARN_ON(action !=3D RIPAS_SET); + WARN_ON(action =3D=3D RIPAS_INIT); } else { WARN_ON(action !=3D RIPAS_INIT); } =20 while (ipa < end) { + unsigned long rtt_tree_idx =3D 0; unsigned long next; =20 switch (action) { @@ -1364,21 +1366,27 @@ static int ripas_change(struct kvm *kvm, ret =3D rmi_rtt_set_ripas(rd_phys, rec_phys, ipa, end, &next); break; + case SET_S2AP: + ret =3D rmi_rtt_set_s2ap(rd_phys, rec_phys, ipa, end, + &next, &rtt_tree_idx); + break; } =20 switch (RMI_RETURN_STATUS(ret)) { case RMI_SUCCESS: ipa =3D next; break; - case RMI_ERROR_RTT: { + case RMI_ERROR_RTT: + case RMI_ERROR_RTT_AUX: { int err_level =3D RMI_RETURN_INDEX(ret); int level =3D find_map_level(realm, ipa, end); =20 if (err_level >=3D level) return -EINVAL; =20 - ret =3D realm_create_rtt_levels(realm, ipa, err_level, - level, memcache); + ret =3D realm_create_rtt_aux_levels(realm, ipa, err_level, + level, rtt_tree_idx, + memcache); if (ret) return ret; /* Retry with the RTT levels in place */ @@ -1396,6 +1404,15 @@ static int ripas_change(struct kvm *kvm, return 0; } =20 +int kvm_realm_set_s2ap(struct kvm_vcpu *vcpu, + unsigned long start, + unsigned long end) +{ + struct kvm *kvm =3D vcpu->kvm; + + return ripas_change(kvm, vcpu, start, end, SET_S2AP, NULL); +} + static int realm_set_ipa_state(struct kvm_vcpu *vcpu, unsigned long start, unsigned long end, --=20 2.43.0