From nobody Thu Apr 9 05:46:32 2026 Received: from mail-wm1-f73.google.com (mail-wm1-f73.google.com [209.85.128.73]) (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 B268040DFC9 for ; Tue, 10 Mar 2026 12:49:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773146986; cv=none; b=jamFPPaozWG7NxSSjgbN/8YtGkMoP9SK1fzwXL2Uz92ZvbYx/+W+lRpY4m6WOSSj/bMw2v4Qw/LHZsAycqAWZf0x3g4XmOxshLabut06wYnkfYSBUUgrlocWm5a/kCU9dJbLLKUQab2kXTIPWcpajw8+r+uzE4ZVGZnnTuARv/Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773146986; c=relaxed/simple; bh=XMezVaG2jrFsqhtuwUE0Kf1BC2hXXFsGiwJ8k7oxih4=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=DMBl5e0ybZ8kkw68i6mzWcEoY4xPGhlpYABIps3f5tWsFHmhJ2afwp06yhgWrAHpWvrywJoD4y8H7uu/I5XkSjWkztkFLnYgpZTkbhVpRR0V+t9+Tn6iF0vCGoi7quftJqhaAn6fEvHPt3KV1jgtqIdR9bPX6vHvsQQ+5c+nxiA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sebastianene.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=pSBRf1Gj; arc=none smtp.client-ip=209.85.128.73 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--sebastianene.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="pSBRf1Gj" Received: by mail-wm1-f73.google.com with SMTP id 5b1f17b1804b1-485390246c8so25975005e9.0 for ; Tue, 10 Mar 2026 05:49:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1773146983; x=1773751783; darn=vger.kernel.org; h=content-transfer-encoding:cc:to:from:subject:message-id:references :mime-version:in-reply-to:date:from:to:cc:subject:date:message-id :reply-to; bh=p112r6vXdhUi4U6D+bqdMKbRGwHW3a/qIYzeua87t30=; b=pSBRf1GjOKf+PJBJFalJnXcRMR3FRcN9I3vghe/FrWBacEYd1AukRGt6SHOFZPPeke ZV+xyYXDMA/V/UM0JA48N5+0F08R/dbjzo5m964uWRXAPwkM/Q54r1aN3hkFzr6ory6a WEEDHxnW2QNdO9hyTzBoulH6iqywpFgmdEoK8juhUnBj+24vJLXRgMEXiNMY2iHkWQ0T gw9IB9pKiAFaxfA6EWHiKaeIvN0M443Hkvr0panmY//VJr9tkqCUjvIl4ZHtZozspQRt I7PxuRrpdrxhTerg1XdUxO0Ej2bwOyHVs4bYiV8l3Wj/KLdIulY1ePOcDZJbFJk8eHff y9Gg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1773146983; x=1773751783; h=content-transfer-encoding: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=p112r6vXdhUi4U6D+bqdMKbRGwHW3a/qIYzeua87t30=; b=ZBlgpw0W4aPsVgfAN5Hnp9ni9i+O2RTZ0xWbrDc7Gx7if/N0ZYmycohh49CqxjBfxS fmh6orUndq6Rg+Uh7BGmF6stFPVcbaTkjqz+Gzb4xP3sgI31TFBipsuqRQUpezz1yuBS ZY7r4lSDTvBroCQEW5PXjdYxml1AcrHkvZLHbhoqHlVw2iit8oUevV8kSEOEuO+iZ3uN bNHR7CIjkI2M9HRuS6q1EGW5h5aIzySO039YESn/l1d1oxCRZuVxfJzwUqhO7kRY+s7c uLJbsPhiCKkLir0BJfgVpLAyl2BMJhkxi443hJ8tBdIoC62BEUvwpFoB/ZokKcC4IkvJ 0xYg== X-Forwarded-Encrypted: i=1; AJvYcCWxDtKDLoNiaj18wJf6ciJXTED8PQN/+wBXhBm1JNt+1O5/JmscGSoAW4snnxdFn6dnSYPrcOnJtydlEqU=@vger.kernel.org X-Gm-Message-State: AOJu0YxbPJATe3C5jjtE1BIpZu4u/1sHx2gqn7UfUXYjALLd1wwyQABV oZhyAd4Du5h92sCLW+UAl73m5eYYMsX/Aht44zhgbkF8HcANjDEWOkYqmQo1BEmRlmoP0ynCc/9 lmbPRNcubPBt8Vff5SUupba8ojrG1GA== X-Received: from wmbfp26.prod.google.com ([2002:a05:600c:699a:b0:485:29bb:91fc]) (user=sebastianene job=prod-delivery.src-stubby-dispatcher) by 2002:a05:600c:8485:b0:485:3fe6:2209 with SMTP id 5b1f17b1804b1-4853fe622dcmr81484045e9.11.1773146983096; Tue, 10 Mar 2026 05:49:43 -0700 (PDT) Date: Tue, 10 Mar 2026 12:49:20 +0000 In-Reply-To: <20260310124933.830025-1-sebastianene@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260310124933.830025-1-sebastianene@google.com> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog Message-ID: <20260310124933.830025-2-sebastianene@google.com> Subject: [PATCH 01/14] KVM: arm64: Donate MMIO to the hypervisor From: Sebastian Ene To: alexandru.elisei@arm.com, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, android-kvm@google.com Cc: catalin.marinas@arm.com, dbrazdil@google.com, joey.gouly@arm.com, kees@kernel.org, mark.rutland@arm.com, maz@kernel.org, oupton@kernel.org, perlarsen@google.com, qperret@google.com, rananta@google.com, sebastianene@google.com, smostafa@google.com, suzuki.poulose@arm.com, tabba@google.com, tglx@kernel.org, vdonnefort@google.com, bgrzesik@google.com, will@kernel.org, yuzenghui@huawei.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Mostafa Saleh Add a function to donate MMIO to the hypervisor so IOMMU hypervisor drivers can use that to protect the MMIO of IOMMU. The initial attempt to implement this was to have a new flag to "___pkvm_host_donate_hyp" to accept MMIO. However that had many problems, it was quite intrusive for host/hyp to check/set page state to make it aware of MMIO and to encode the state in the page table in that case. Which is called in paths that can be sensitive to performance (FFA, VMs..) As donating MMIO is very rare, and we don=E2=80=99t need to encode the full state, it=E2=80=99s reasonable to have a separate function to do this. It will init the host s2 page table with an invalid leaf with the owner ID to prevent the host from mapping the page on faults. Also, prevent kvm_pgtable_stage2_unmap() from removing owner ID from stage-2 PTEs, as this can be triggered from recycle logic under memory pressure. There is no code relying on this, as all ownership changes is done via kvm_pgtable_stage2_set_owner() For error path in IOMMU drivers, add a function to donate MMIO back from hyp to host. Signed-off-by: Mostafa Saleh Reviewed-by: Fuad Tabba --- arch/arm64/kvm/hyp/include/nvhe/mem_protect.h | 2 + arch/arm64/kvm/hyp/nvhe/mem_protect.c | 90 +++++++++++++++++++ arch/arm64/kvm/hyp/pgtable.c | 9 +- 3 files changed, 94 insertions(+), 7 deletions(-) diff --git a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h b/arch/arm64/kvm= /hyp/include/nvhe/mem_protect.h index 5f9d56754e39..8b617e6fc0e0 100644 --- a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h +++ b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h @@ -31,6 +31,8 @@ enum pkvm_component_id { }; =20 extern unsigned long hyp_nr_cpus; +int __pkvm_host_donate_hyp_mmio(u64 pfn); +int __pkvm_hyp_donate_host_mmio(u64 pfn); =20 int __pkvm_prot_finalize(void); int __pkvm_host_share_hyp(u64 pfn); diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvh= e/mem_protect.c index 38f66a56a766..0808367c52e5 100644 --- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c +++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c @@ -784,6 +784,96 @@ int __pkvm_host_unshare_hyp(u64 pfn) return ret; } =20 +int __pkvm_host_donate_hyp_mmio(u64 pfn) +{ + u64 phys =3D hyp_pfn_to_phys(pfn); + void *virt =3D __hyp_va(phys); + int ret; + kvm_pte_t pte; + + if (addr_is_memory(phys)) + return -EINVAL; + + host_lock_component(); + hyp_lock_component(); + + ret =3D kvm_pgtable_get_leaf(&host_mmu.pgt, phys, &pte, NULL); + if (ret) + goto unlock; + + if (pte && !kvm_pte_valid(pte)) { + ret =3D -EPERM; + goto unlock; + } + + ret =3D kvm_pgtable_get_leaf(&pkvm_pgtable, (u64)virt, &pte, NULL); + if (ret) + goto unlock; + if (pte) { + ret =3D -EBUSY; + goto unlock; + } + + ret =3D pkvm_create_mappings_locked(virt, virt + PAGE_SIZE, PAGE_HYP_DEVI= CE); + if (ret) + goto unlock; + /* + * We set HYP as the owner of the MMIO pages in the host stage-2, for: + * - host aborts: host_stage2_adjust_range() would fail for invalid non z= ero PTEs. + * - recycle under memory pressure: host_stage2_unmap_dev_all() would call + * kvm_pgtable_stage2_unmap() which will not clear non zero invalid pte= s (counted). + * - other MMIO donation: Would fail as we check that the PTE is valid or= empty. + */ + WARN_ON(host_stage2_try(kvm_pgtable_stage2_set_owner, &host_mmu.pgt, phys, + PAGE_SIZE, &host_s2_pool, PKVM_ID_HYP)); +unlock: + hyp_unlock_component(); + host_unlock_component(); + + return ret; +} + +int __pkvm_hyp_donate_host_mmio(u64 pfn) +{ + u64 phys =3D hyp_pfn_to_phys(pfn); + u64 virt =3D (u64)__hyp_va(phys); + size_t size =3D PAGE_SIZE; + int ret; + kvm_pte_t pte; + + if (addr_is_memory(phys)) + return -EINVAL; + + host_lock_component(); + hyp_lock_component(); + + ret =3D kvm_pgtable_get_leaf(&pkvm_pgtable, (u64)virt, &pte, NULL); + if (ret) + goto unlock; + if (!kvm_pte_valid(pte)) { + ret =3D -ENOENT; + goto unlock; + } + + ret =3D kvm_pgtable_get_leaf(&host_mmu.pgt, phys, &pte, NULL); + if (ret) + goto unlock; + + if (FIELD_GET(KVM_INVALID_PTE_OWNER_MASK, pte) !=3D PKVM_ID_HYP) { + ret =3D -EPERM; + goto unlock; + } + + WARN_ON(kvm_pgtable_hyp_unmap(&pkvm_pgtable, virt, size) !=3D size); + WARN_ON(host_stage2_try(kvm_pgtable_stage2_set_owner, &host_mmu.pgt, phys, + PAGE_SIZE, &host_s2_pool, PKVM_ID_HOST)); +unlock: + hyp_unlock_component(); + host_unlock_component(); + + return ret; +} + int __pkvm_host_donate_hyp(u64 pfn, u64 nr_pages) { u64 phys =3D hyp_pfn_to_phys(pfn); diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c index 9b480f947da2..d954058e63ff 100644 --- a/arch/arm64/kvm/hyp/pgtable.c +++ b/arch/arm64/kvm/hyp/pgtable.c @@ -1152,13 +1152,8 @@ static int stage2_unmap_walker(const struct kvm_pgta= ble_visit_ctx *ctx, kvm_pte_t *childp =3D NULL; bool need_flush =3D false; =20 - if (!kvm_pte_valid(ctx->old)) { - if (stage2_pte_is_counted(ctx->old)) { - kvm_clear_pte(ctx->ptep); - mm_ops->put_page(ctx->ptep); - } - return 0; - } + if (!kvm_pte_valid(ctx->old)) + return stage2_pte_is_counted(ctx->old) ? -EPERM : 0; =20 if (kvm_pte_table(ctx->old, ctx->level)) { childp =3D kvm_pte_follow(ctx->old, mm_ops); --=20 2.53.0.473.g4a7958ca14-goog From nobody Thu Apr 9 05:46:32 2026 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 0993940DFD5 for ; Tue, 10 Mar 2026 12:49:46 +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=1773146987; cv=none; b=uUHXOheH3jHKAyGXqMbIZM6VysPgFJsHjo+u5DSyvJr8juILh2N3oXd+xbcLdRNwerjHgZUZNlqcQUrgXEHkhlxvJd43uIVT/gxCoGKFIl9FrxjZ0K1j3cDucd54aGjAvHS5kqrUTH/0boKyPpu1YdVVQX1k9SimVo5vlOEBizA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773146987; c=relaxed/simple; bh=24ri8I0HdHMqey03lI4dSqJ6RSKEZnF/Gr6nhwOJ9lg=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=bJ29h/bzaRRHkycs1MYcrPYS0dULKzsbsr6CCbcgssLrsO9Kj1fpVFzwAvCApq855Zs4cPfwsmwXn4fDdmk2jXbEsiFpIwc+YMiZwQjRktkFbe8ggNGY7u9ERkBrv6eLQKwgNiR1wacxMTCEp3CGj9+OwPw0k0r9KJwUPayF+BE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sebastianene.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=OKdPyzQr; 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--sebastianene.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="OKdPyzQr" Received: by mail-wm1-f74.google.com with SMTP id 5b1f17b1804b1-485355493aeso12552675e9.1 for ; Tue, 10 Mar 2026 05:49:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1773146984; x=1773751784; 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=FjEHtrJ78MYHEp21ejNh5LanY+xm4uc/Zo9pOF+NIDo=; b=OKdPyzQrfR1pQ4uARn2of0kPsBkmzAgsd4yo2JE10tqYEEQGMeFiEBRPFBq2jdoOr0 qTJ8Gv1YIw/V9Iyhf0LZ7C2/VQh8u9PMbX9/fUKyrheca+7OdCmH9N0urvi5dVatlqQZ MRI1rXkRqRNAhTSFOlBE3kWheGG+2MnqkP24/h3U0otHheTlTUhd+7+67zHue8HJn3EV XuEDb+LqVykwTPIBnnrAvskl+ZzBXEUSdM1Ny9naAH/xNQjLBnUyqH4hhzRE4pVr90u/ uaU+LFsMXR49wvcK2aNep+XFVSsaHG9VC4MZDqX+wdrCQznlJPLEvMqANghuayGD3+T7 U2ug== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1773146984; x=1773751784; 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=FjEHtrJ78MYHEp21ejNh5LanY+xm4uc/Zo9pOF+NIDo=; b=iwNE7BpZr8LTRjsrhmreXGTuq5fSCEbbMwVGxMxi9ZYAbjKaxDUqmPSIYgoi0wx9xT LunxeLGVYFruyQhjabTgJd8iyS29MjmUfjmUMC/8YHi0YAkN0QtQI5rCAXvyy40JGt9Z QwtnuloKtn4l5nY3dHon++kowjJf6oOuVxu1LZwXiC3rtMth4gza0Del4hDahofOx25S nT0kuyB6x8cY/0YLx7KC4l073Uv6YPAJaFYslRvIFRC0ap23FG9AoTYoVkc4HvhjkHMt +srIFMZJOxwHhjTZWcvdHhCU7WKTAyFzIGMNCAeajVwfknFDgckdPNhp2Kc3sW3ytGni RHHg== X-Forwarded-Encrypted: i=1; AJvYcCU+VvVN1ceG5AksnAXwZ2dTB4fkIOJdtD2z1SfQYNbW58Djes2FPlZY90+K/95LOyt2ppBmOhbXzOkcjdw=@vger.kernel.org X-Gm-Message-State: AOJu0Yx++lV4WFPXfw8mECq5m2ncPO3frzQAoZ0CXL+Oj+ScDdj0C45A xQwWaAvykYvqnlgrCnrYeU3xlpWRMfDtAoxU09F5pJd3NE9Vtv08waVcf/p+fZP0hqWO41kaw2Q Kfj/CYF2Jzlf890epHb1SJvKBhSbOEw== X-Received: from wmqn19.prod.google.com ([2002:a05:600c:4f93:b0:483:a1ee:5eb8]) (user=sebastianene job=prod-delivery.src-stubby-dispatcher) by 2002:a05:600c:4fc5:b0:485:3b34:2f62 with SMTP id 5b1f17b1804b1-4853b343050mr131705485e9.14.1773146984437; Tue, 10 Mar 2026 05:49:44 -0700 (PDT) Date: Tue, 10 Mar 2026 12:49:21 +0000 In-Reply-To: <20260310124933.830025-1-sebastianene@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260310124933.830025-1-sebastianene@google.com> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog Message-ID: <20260310124933.830025-3-sebastianene@google.com> Subject: [PATCH 02/14] KVM: arm64: Track host-unmapped MMIO regions in a static array From: Sebastian Ene To: alexandru.elisei@arm.com, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, android-kvm@google.com Cc: catalin.marinas@arm.com, dbrazdil@google.com, joey.gouly@arm.com, kees@kernel.org, mark.rutland@arm.com, maz@kernel.org, oupton@kernel.org, perlarsen@google.com, qperret@google.com, rananta@google.com, sebastianene@google.com, smostafa@google.com, suzuki.poulose@arm.com, tabba@google.com, tglx@kernel.org, vdonnefort@google.com, bgrzesik@google.com, will@kernel.org, yuzenghui@huawei.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Introduce a registry to track protected MMIO regions that are unmapped from the host stage-2 page tables. These regions are stored in a fixed-size array and their ownership is donated to the hypervisor during initialization to ensure host-exclusion and persistent tracking. Signed-off-by: Sebastian Ene --- arch/arm64/include/asm/kvm_pkvm.h | 10 ++++++++++ arch/arm64/kvm/hyp/nvhe/mem_protect.c | 3 +++ arch/arm64/kvm/hyp/nvhe/setup.c | 25 +++++++++++++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/arch/arm64/include/asm/kvm_pkvm.h b/arch/arm64/include/asm/kvm= _pkvm.h index 757076ad4ec9..48ec7d519399 100644 --- a/arch/arm64/include/asm/kvm_pkvm.h +++ b/arch/arm64/include/asm/kvm_pkvm.h @@ -17,6 +17,16 @@ =20 #define HYP_MEMBLOCK_REGIONS 128 =20 +#define PKVM_PROTECTED_REGS_NUM 8 + +struct pkvm_protected_reg { + u64 start_pfn; + size_t num_pages; +}; + +extern struct pkvm_protected_reg kvm_nvhe_sym(pkvm_protected_regs)[]; +extern unsigned int kvm_nvhe_sym(num_protected_reg); + int pkvm_init_host_vm(struct kvm *kvm); int pkvm_create_hyp_vm(struct kvm *kvm); bool pkvm_hyp_vm_is_created(struct kvm *kvm); diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvh= e/mem_protect.c index 0808367c52e5..7c125836b533 100644 --- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c +++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c @@ -23,6 +23,9 @@ =20 struct host_mmu host_mmu; =20 +struct pkvm_protected_reg pkvm_protected_regs[PKVM_PROTECTED_REGS_NUM]; +unsigned int num_protected_reg; + static struct hyp_pool host_s2_pool; =20 static DEFINE_PER_CPU(struct pkvm_hyp_vm *, __current_vm); diff --git a/arch/arm64/kvm/hyp/nvhe/setup.c b/arch/arm64/kvm/hyp/nvhe/setu= p.c index 90bd014e952f..ad5b96085e1b 100644 --- a/arch/arm64/kvm/hyp/nvhe/setup.c +++ b/arch/arm64/kvm/hyp/nvhe/setup.c @@ -284,6 +284,27 @@ static int fix_hyp_pgtable_refcnt(void) &walker); } =20 +static int unmap_protected_regions(void) +{ + struct pkvm_protected_reg *reg; + int i, ret, j =3D 0; + + for (i =3D 0; i < num_protected_reg; i++) { + reg =3D &pkvm_protected_regs[i]; + for (j =3D 0; j < reg->num_pages; j++) { + ret =3D __pkvm_host_donate_hyp_mmio(reg->start_pfn + j); + if (ret) + goto err_setup; + } + } + + return 0; +err_setup: + for (j =3D j - 1; j >=3D 0; j--) + __pkvm_hyp_donate_host_mmio(reg->start_pfn + j); + return ret; +} + void __noreturn __pkvm_init_finalise(void) { struct kvm_cpu_context *host_ctxt =3D host_data_ptr(host_ctxt); @@ -324,6 +345,10 @@ void __noreturn __pkvm_init_finalise(void) if (ret) goto out; =20 + ret =3D unmap_protected_regions(); + if (ret) + goto out; + ret =3D hyp_ffa_init(ffa_proxy_pages); if (ret) goto out; --=20 2.53.0.473.g4a7958ca14-goog From nobody Thu Apr 9 05:46:32 2026 Received: from mail-wr1-f74.google.com (mail-wr1-f74.google.com [209.85.221.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 4CDE22949E0 for ; Tue, 10 Mar 2026 12:49:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773146988; cv=none; b=G+G1cqZVPc2ITzS5Rr+4x2BuNV4EbjQqNF08hJ1Hwe1XWdxHVB1IW3j/wJ0ZlBR1uPPveD2N/Q0kvKJB8yU3iFmWaHK6ZzWOGzs2htdRSmkSqKavagQoudBaqj2d7D+UYtPG0JjCz+JYgc1rxit8vINte9sTBkVLGRxoSCxs8Q8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773146988; c=relaxed/simple; bh=da9sGRb1sXtZYbXldYQiInn/poIF06gS77aMtCUZDOs=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=iboMrnUt75+Ct4MiWgPAS7rlGs4fERHvNy2uGxFA0eHQaF1a+4KA7ise4XF12H3kcSMNK2EFdUPQAHLhXlj0UrvD49xu18aLDodOu1wflKr/fZofnABuqFIbTczQaOrWzI24PfR2BwWUb8gdQlRaG3B4IPbQs2M1NUN6wU02OA0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sebastianene.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=2Nu81cc0; arc=none smtp.client-ip=209.85.221.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--sebastianene.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="2Nu81cc0" Received: by mail-wr1-f74.google.com with SMTP id ffacd0b85a97d-439cbfcfc21so6580047f8f.2 for ; Tue, 10 Mar 2026 05:49:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1773146986; x=1773751786; 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=ToBQfETgLJjiDxh0mdZ0jWyVKcLeeqGXYElZ0/3fbdc=; b=2Nu81cc0r6fwdd5vQDIP5//DAT5l4i0gP/bMgKj1XpX334ycEEoaVJE9eTS4XIQ6OY yKJALKdsRg5JTg6GfAZCGTVWs8YT9N/YkGaqCR2aySQeJYdA3ewCoohKrL6JUdvVz1V1 RihQ3HJbkht231WW9k20g4xHb5j+9DdU66/VtVV+h3uOecyQ/3TH/IQzkJOSbxcRn+Xl uH1Rcmh4eA7hV2Ma4fqKWTTNHOyPVq338Zre7Mr5C3yNLVSt74JBAAw3kEL7WoG/oQjn OoB2v23vOznVa7g453GQJdI06RLkyMJNaQmzMhkDHwFlRBO84oOL4LKj5eoqLfY7+eTg yMmg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1773146986; x=1773751786; 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=ToBQfETgLJjiDxh0mdZ0jWyVKcLeeqGXYElZ0/3fbdc=; b=Ow5QBDfvG/Jdr0xFLEDjE1mZrS2SDTzSyz4GxpZteHwlgGIHZBf1CtRXCJYdSZMp2x lDglZO5vUAlZwSaGQP3ZHoRdQArNhaBkTS67D2aC4i8KNRTItLyTTEIx61btfsFxeY07 02m0sYPgf5D1/NFLD2Xa67oMLOmkpIy7ePuhO3CBGWnywNLVZkLsPI8tr3i5Q27B0E+8 sKu++4LgXL3yBx65nqTCLzQPpxqTcQTczKCdmF71Spb3csOg31TaFh84LGWM6MVWjANL HJhGWLPWWubd+5yYbWnoxErx26ai8LiX9GYLPJMazcEEXrnndYCtlwHB4gZWgnj98sV6 YnIw== X-Forwarded-Encrypted: i=1; AJvYcCXA2ElGXm7cQjlGtJ3x3Jde0hWrJZiRD0r7gbrLs7erhRP0fwf1gNyHBAEYHmKW93cyZupYTMOQ7tQrBU4=@vger.kernel.org X-Gm-Message-State: AOJu0Yy0t6+6qfRgwxI0X6hNVgPoT5/N7B7hrAk0luZOVi/yyWccsj9f 8ieZs3L30NE8xEIEcyPqFzPGW6z7jCr521X4jdQvqc9RWeoA5s+OlqE8+sPci7IKeD4HR2sfVlj QlRzjEPSd3ouybrNa2fjXti2A9yXy2w== X-Received: from wrdf12.prod.google.com ([2002:a5d:58ec:0:b0:439:b20b:f16a]) (user=sebastianene job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6000:2285:b0:439:ba69:101d with SMTP id ffacd0b85a97d-439da354ccbmr25716640f8f.1.1773146985467; Tue, 10 Mar 2026 05:49:45 -0700 (PDT) Date: Tue, 10 Mar 2026 12:49:22 +0000 In-Reply-To: <20260310124933.830025-1-sebastianene@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260310124933.830025-1-sebastianene@google.com> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog Message-ID: <20260310124933.830025-4-sebastianene@google.com> Subject: [PATCH 03/14] KVM: arm64: Support host MMIO trap handlers for unmapped devices From: Sebastian Ene To: alexandru.elisei@arm.com, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, android-kvm@google.com Cc: catalin.marinas@arm.com, dbrazdil@google.com, joey.gouly@arm.com, kees@kernel.org, mark.rutland@arm.com, maz@kernel.org, oupton@kernel.org, perlarsen@google.com, qperret@google.com, rananta@google.com, sebastianene@google.com, smostafa@google.com, suzuki.poulose@arm.com, tabba@google.com, tglx@kernel.org, vdonnefort@google.com, bgrzesik@google.com, will@kernel.org, yuzenghui@huawei.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Introduce a mechanism to register callbacks for MMIO accesses to regions unmapped from the host Stage-2 page tables. This infrastructure allows the hypervisor to intercept host accesses to protected or emulated devices. When a Stage-2 fault occurs on a registered device region, the hypervisor will invoke the associated callback to emulate the access. Signed-off-by: Sebastian Ene --- arch/arm64/include/asm/kvm_arm.h | 3 ++ arch/arm64/include/asm/kvm_pkvm.h | 6 ++++ arch/arm64/kvm/hyp/nvhe/mem_protect.c | 41 +++++++++++++++++++++++++++ arch/arm64/kvm/hyp/nvhe/setup.c | 3 ++ 4 files changed, 53 insertions(+) diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_= arm.h index 3f9233b5a130..8fe1e80ab3f4 100644 --- a/arch/arm64/include/asm/kvm_arm.h +++ b/arch/arm64/include/asm/kvm_arm.h @@ -304,6 +304,9 @@ =20 /* Hyp Prefetch Fault Address Register (HPFAR/HDFAR) */ #define HPFAR_MASK (~UL(0xf)) + +#define FAR_MASK GENMASK_ULL(11, 0) + /* * We have * PAR [PA_Shift - 1 : 12] =3D PA [PA_Shift - 1 : 12] diff --git a/arch/arm64/include/asm/kvm_pkvm.h b/arch/arm64/include/asm/kvm= _pkvm.h index 48ec7d519399..5321ced2f50a 100644 --- a/arch/arm64/include/asm/kvm_pkvm.h +++ b/arch/arm64/include/asm/kvm_pkvm.h @@ -19,9 +19,15 @@ =20 #define PKVM_PROTECTED_REGS_NUM 8 =20 +struct pkvm_protected_reg; + +typedef void (pkvm_emulate_handler)(struct pkvm_protected_reg *region, u64= offset, bool write, + u64 *reg, u8 reg_size); + struct pkvm_protected_reg { u64 start_pfn; size_t num_pages; + pkvm_emulate_handler *cb; }; =20 extern struct pkvm_protected_reg kvm_nvhe_sym(pkvm_protected_regs)[]; diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvh= e/mem_protect.c index 7c125836b533..f405d2fbd88f 100644 --- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c +++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c @@ -13,6 +13,7 @@ #include =20 #include +#include =20 #include #include @@ -608,6 +609,41 @@ static int host_stage2_idmap(u64 addr) return ret; } =20 +static bool handle_host_mmio_trap(struct kvm_cpu_context *host_ctxt, u64 e= sr, u64 addr) +{ + u64 offset, reg_value =3D 0, start, end; + u8 reg_size, reg_index; + bool write; + int i; + + for (i =3D 0; i < num_protected_reg; i++) { + start =3D pkvm_protected_regs[i].start_pfn << PAGE_SHIFT; + end =3D start + (pkvm_protected_regs[i].num_pages << PAGE_SHIFT); + + if (start > addr || addr > end) + continue; + + reg_size =3D BIT((esr & ESR_ELx_SAS) >> ESR_ELx_SAS_SHIFT); + reg_index =3D (esr & ESR_ELx_SRT_MASK) >> ESR_ELx_SRT_SHIFT; + write =3D (esr & ESR_ELx_WNR) =3D=3D ESR_ELx_WNR; + offset =3D addr - start; + + if (write) + reg_value =3D host_ctxt->regs.regs[reg_index]; + + pkvm_protected_regs[i].cb(&pkvm_protected_regs[i], offset, write, + ®_value, reg_size); + + if (!write) + host_ctxt->regs.regs[reg_index] =3D reg_value; + + kvm_skip_host_instr(); + return true; + } + + return false; +} + void handle_host_mem_abort(struct kvm_cpu_context *host_ctxt) { struct kvm_vcpu_fault_info fault; @@ -630,6 +666,11 @@ void handle_host_mem_abort(struct kvm_cpu_context *hos= t_ctxt) */ BUG_ON(!(fault.hpfar_el2 & HPFAR_EL2_NS)); addr =3D FIELD_GET(HPFAR_EL2_FIPA, fault.hpfar_el2) << 12; + addr |=3D fault.far_el2 & FAR_MASK; + + if (ESR_ELx_EC(esr) =3D=3D ESR_ELx_EC_DABT_LOW && !addr_is_memory(addr) && + handle_host_mmio_trap(host_ctxt, esr, addr)) + return; =20 ret =3D host_stage2_idmap(addr); BUG_ON(ret && ret !=3D -EAGAIN); diff --git a/arch/arm64/kvm/hyp/nvhe/setup.c b/arch/arm64/kvm/hyp/nvhe/setu= p.c index ad5b96085e1b..f91dfebe9980 100644 --- a/arch/arm64/kvm/hyp/nvhe/setup.c +++ b/arch/arm64/kvm/hyp/nvhe/setup.c @@ -296,6 +296,9 @@ static int unmap_protected_regions(void) if (ret) goto err_setup; } + + if (reg->cb) + reg->cb =3D kern_hyp_va(reg->cb); } =20 return 0; --=20 2.53.0.473.g4a7958ca14-goog From nobody Thu Apr 9 05:46:32 2026 Received: from mail-wm1-f73.google.com (mail-wm1-f73.google.com [209.85.128.73]) (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 44C5D38B143 for ; Tue, 10 Mar 2026 12:49:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773146990; cv=none; b=eBMtXfbTf3ze1ZZLEMreLcpjKZia31b+MiPgccjwhT0WHC1INHKGPhQW178qGi1qEU5CF6YZK4TbE8usXsvdrhwcJY/n/oF/pt6sORmCEq/Zo/8DsfVbmlPRPqZ7sVeicSavaPyLvVNak6Sy054g38U+nJtfjXFArL4kpLwDKuQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773146990; c=relaxed/simple; bh=14KappcwlVf4yuTAUqr072Clw0Dq8rqsTruC9Z7bLgk=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=eq3AWzWSLwE+nGCCqFog9uVSpUtd0EVRNj7y0WgT0jo5pi3/x9HE3Bzgw3qRDVLKMVIH1t+eXdKHm/vVeoXBOyMVAM5uhQbcppRPE2PlLpWswwuxbOzEK8DRXlmDqFc+rAttK6E4I0JBcKyXpv4qyxtIou6exymxEFdJ968gT0c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sebastianene.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=XHkA3rf0; arc=none smtp.client-ip=209.85.128.73 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--sebastianene.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="XHkA3rf0" Received: by mail-wm1-f73.google.com with SMTP id 5b1f17b1804b1-4853ab1cae0so20355015e9.2 for ; Tue, 10 Mar 2026 05:49:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1773146987; x=1773751787; 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=l6n5Y9iqY7rq1n5Q/lgdkU3SuBp6Rv+RQlbX0vgQT/A=; b=XHkA3rf0cGVvyL8At2cyLLuLNnBaVw0g7jRTW8JsN6q6xsenkK3sCQMYAZs/OL1+Eg RLCMm6qIpNOs8CNZ6LxPfksD3gawfIKVBVHFRQ2D1DuWeaf8XYwQmcAmv565L2hyUeDT P3El7Hd3wXPRU1+oNqZBvuLpYnRF1Hh714YtKQEUaTPurFC0TKOCW7+8OGNwGOgcvYkB mJSXn3x2YU0dHH/RlnajBR4rqZfhuQX9LtKW+ahn0ckWY3ldJ/c0aKdhc90f6VvX6GMH bTZwTRpGEdFy4SobyjFXnTZ0C8QDSk5DGeesDBevF6Kp/YFk7dBJvTctsNTOLW9qG5nV DxcA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1773146987; x=1773751787; 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=l6n5Y9iqY7rq1n5Q/lgdkU3SuBp6Rv+RQlbX0vgQT/A=; b=mmq+3b3lGLsKbbgfr3qyTq5tpfVrDXLLxZ72xw0hwnWU7f9Q/T5z3ZxK6xqsWSUsvX SWmOo5wVY3g+FVqoxikcERLdFw8svjR8FUQBrjifLkaJomuhyV61reITYTlWHUK/+esM +K65tBBecQF8FpXOkTjlUL4GNXKciYgUnqttsqkJ6EPXtyeiwQj8krhr0+wq+XOcs4L2 BJT/CNwicB1Um+tcig8vTNuWzZV3NdY2fFzq6S/mlv6wGhLCXeg7uNojWOQwAq583qz0 RdXBRUBuFsPYX37DDAs48ueu3KuUBLcUaHciabnyHK7HWUToiMiMsIwoqW/g0ji6EPLN qSYg== X-Forwarded-Encrypted: i=1; AJvYcCVIlFhRGWMwghztEqKHMQHIwFhWRvTJWEp0tnKOUIOCahAh8KbjLV+O0cGCJpWT7qkYQ/Qteu3kbY/A68Y=@vger.kernel.org X-Gm-Message-State: AOJu0YwVdoWUl2654ZXYETDFqx+JTCYjG9hM/UdBET8wHmqbzxxqZ3dr f+I00EZUlJ58eD0/8H7LeEPK2li8EUpBdmwe/lDBk8XsjHoKdSNdV0PHUiS5kI7uqgVbpVUXpuI oIHzHd6L//OpXz1v3KVqHN9lCUtSX4Q== X-Received: from wmby21.prod.google.com ([2002:a05:600c:c055:b0:485:343f:9fb3]) (user=sebastianene job=prod-delivery.src-stubby-dispatcher) by 2002:a05:600c:138a:b0:477:7ae0:cd6e with SMTP id 5b1f17b1804b1-485269196ffmr271672925e9.5.1773146986648; Tue, 10 Mar 2026 05:49:46 -0700 (PDT) Date: Tue, 10 Mar 2026 12:49:23 +0000 In-Reply-To: <20260310124933.830025-1-sebastianene@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260310124933.830025-1-sebastianene@google.com> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog Message-ID: <20260310124933.830025-5-sebastianene@google.com> Subject: [PATCH 04/14] KVM: arm64: Mediate host access to GIC/ITS MMIO via unmapping From: Sebastian Ene To: alexandru.elisei@arm.com, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, android-kvm@google.com Cc: catalin.marinas@arm.com, dbrazdil@google.com, joey.gouly@arm.com, kees@kernel.org, mark.rutland@arm.com, maz@kernel.org, oupton@kernel.org, perlarsen@google.com, qperret@google.com, rananta@google.com, sebastianene@google.com, smostafa@google.com, suzuki.poulose@arm.com, tabba@google.com, tglx@kernel.org, vdonnefort@google.com, bgrzesik@google.com, will@kernel.org, yuzenghui@huawei.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Unmap the ITS MMIO region from the host address space to enforce hypervisor mediation. Identify the ITS base address from the device tree and store it in a protected region. A callback is registered to handle host accesses to this region; currently, the handler simply forwards all MMIO requests to the physical hardware. This provides the infrastructure for future hardware state validation without changing current behavior. Signed-off-by: Sebastian Ene --- arch/arm64/include/asm/kvm_pkvm.h | 2 ++ arch/arm64/kvm/hyp/nvhe/Makefile | 3 ++- arch/arm64/kvm/hyp/nvhe/its_emulate.c | 23 ++++++++++++++++ arch/arm64/kvm/pkvm.c | 38 +++++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 arch/arm64/kvm/hyp/nvhe/its_emulate.c diff --git a/arch/arm64/include/asm/kvm_pkvm.h b/arch/arm64/include/asm/kvm= _pkvm.h index 5321ced2f50a..ef00c1bf7d00 100644 --- a/arch/arm64/include/asm/kvm_pkvm.h +++ b/arch/arm64/include/asm/kvm_pkvm.h @@ -32,6 +32,8 @@ struct pkvm_protected_reg { =20 extern struct pkvm_protected_reg kvm_nvhe_sym(pkvm_protected_regs)[]; extern unsigned int kvm_nvhe_sym(num_protected_reg); +extern void kvm_nvhe_sym(pkvm_handle_forward_req)(struct pkvm_protected_re= g *region, u64 offset, + bool write, u64 *reg, u8 reg_size); =20 int pkvm_init_host_vm(struct kvm *kvm); int pkvm_create_hyp_vm(struct kvm *kvm); diff --git a/arch/arm64/kvm/hyp/nvhe/Makefile b/arch/arm64/kvm/hyp/nvhe/Mak= efile index a244ec25f8c5..eb43269fbac2 100644 --- a/arch/arm64/kvm/hyp/nvhe/Makefile +++ b/arch/arm64/kvm/hyp/nvhe/Makefile @@ -24,7 +24,8 @@ CFLAGS_switch.nvhe.o +=3D -Wno-override-init =20 hyp-obj-y :=3D timer-sr.o sysreg-sr.o debug-sr.o switch.o tlb.o hyp-init.o= host.o \ hyp-main.o hyp-smp.o psci-relay.o early_alloc.o page_alloc.o \ - cache.o setup.o mm.o mem_protect.o sys_regs.o pkvm.o stacktrace.o ffa.o + cache.o setup.o mm.o mem_protect.o sys_regs.o pkvm.o stacktrace.o ffa.o \ + its_emulate.o hyp-obj-y +=3D ../vgic-v3-sr.o ../aarch32.o ../vgic-v2-cpuif-proxy.o ../en= try.o \ ../fpsimd.o ../hyp-entry.o ../exception.o ../pgtable.o hyp-obj-y +=3D ../../../kernel/smccc-call.o diff --git a/arch/arm64/kvm/hyp/nvhe/its_emulate.c b/arch/arm64/kvm/hyp/nvh= e/its_emulate.c new file mode 100644 index 000000000000..0eecbb011898 --- /dev/null +++ b/arch/arm64/kvm/hyp/nvhe/its_emulate.c @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include + + +void pkvm_handle_forward_req(struct pkvm_protected_reg *region, u64 offset= , bool write, + u64 *reg, u8 reg_size) +{ + void __iomem *addr =3D __hyp_va((region->start_pfn << PAGE_SHIFT) + offse= t); + + if (reg_size =3D=3D sizeof(u32)) { + if (!write) + *reg =3D readl_relaxed(addr); + else + writel_relaxed(*reg, addr); + } else if (reg_size =3D=3D sizeof(u64)) { + if (!write) + *reg =3D readq_relaxed(addr); + else + writeq_relaxed(*reg, addr); + } +} diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c index d7a0f69a9982..a766be6de735 100644 --- a/arch/arm64/kvm/pkvm.c +++ b/arch/arm64/kvm/pkvm.c @@ -11,6 +11,9 @@ #include #include #include +#include +#include +#include =20 #include =20 @@ -18,6 +21,7 @@ =20 DEFINE_STATIC_KEY_FALSE(kvm_protected_mode_initialized); =20 +static struct pkvm_protected_reg *pkvm_protected_regs =3D kvm_nvhe_sym(pkv= m_protected_regs); static struct memblock_region *hyp_memory =3D kvm_nvhe_sym(hyp_memory); static unsigned int *hyp_memblock_nr_ptr =3D &kvm_nvhe_sym(hyp_memblock_nr= ); =20 @@ -39,6 +43,34 @@ static int __init register_memblock_regions(void) return 0; } =20 +static int __init register_protected_regions(void) +{ + int i =3D 0, ret; + struct device_node *np; + struct resource res; + + for_each_compatible_node(np, NULL, "arm,gic-v3-its") { + ret =3D of_address_to_resource(np, i, &res); + if (ret) + return ret; + + if (i >=3D PKVM_PROTECTED_REGS_NUM) + return -ENOMEM; + + if (!PAGE_ALIGNED(res.start) || !PAGE_ALIGNED(resource_size(&res))) + return -EINVAL; + + pkvm_protected_regs[i].start_pfn =3D res.start >> PAGE_SHIFT; + pkvm_protected_regs[i].num_pages =3D resource_size(&res) >> PAGE_SHIFT; + pkvm_protected_regs[i].cb =3D lm_alias(&kvm_nvhe_sym(pkvm_handle_forward= _req)); + i++; + } + + kvm_nvhe_sym(num_protected_reg) =3D i; + + return 0; +} + void __init kvm_hyp_reserve(void) { u64 hyp_mem_pages =3D 0; @@ -57,6 +89,12 @@ void __init kvm_hyp_reserve(void) return; } =20 + ret =3D register_protected_regions(); + if (ret) { + kvm_err("Failed to register protected reg: %d\n", ret); + return; + } + hyp_mem_pages +=3D hyp_s1_pgtable_pages(); hyp_mem_pages +=3D host_s2_pgtable_pages(); hyp_mem_pages +=3D hyp_vm_table_pages(); --=20 2.53.0.473.g4a7958ca14-goog From nobody Thu Apr 9 05:46:32 2026 Received: from mail-wm1-f73.google.com (mail-wm1-f73.google.com [209.85.128.73]) (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 81E303A5448 for ; Tue, 10 Mar 2026 12:49:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773146992; cv=none; b=PNi3eKaCd/0VNIEcbL8M8HfTCTe5n2/htG7CEBBOQhdxLynk3+ZNUD+PqEQ50WJ4JK2P53dwdeWNDCwouiFF+7IBwswOjCzGHiTKn8r3LtKkqUOwoOJs5ev5sCrtnHU2MQNKZTZr+l9F4HA2n+k9A3QN2BlejEyu7zSePRXh4cw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773146992; c=relaxed/simple; bh=FR2M+E90Y1v5dC4HO5pEPtueuObDehuxAUbp0SHmBiQ=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=Ubi4Zq47vqS1xZHjA/T+JapED1mDFMl8pqViwT2RxX6+d+7Bbumiot8l0ZxSjabBDoy9+9hugRapzqTc4bVgYztZVGSJe49I5VXOnVUhm9S/D/Aq9DgwYUl4DyDFM9/8MDYHXUTyc0w1nxMAhqvhguDiM3hU/Lv+RsMHU2CziVE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sebastianene.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=z5q5ntKk; arc=none smtp.client-ip=209.85.128.73 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--sebastianene.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="z5q5ntKk" Received: by mail-wm1-f73.google.com with SMTP id 5b1f17b1804b1-4853efceaddso15498515e9.3 for ; Tue, 10 Mar 2026 05:49:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1773146988; x=1773751788; 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=IBw8//o/FKk+iSUCDuIRcFnfCH+1hN6m93POT/Oa1kE=; b=z5q5ntKkzoWVwqAChirkfH6/5TLkLiveNkngJibNKadHKa2PIl9JRgVEByhKc0cDMs /YhyH8ESwO1uw2lESEndclA1SapykexReqzcaDdpCj0MOzdQS9Xa4Zs2ZT/D1cQfFJBx 8dFVdr0/OdTxkApMDQ66eMv6c6mq46Ebql7ndSpUU7/qLVwLHng5GZBPzaY1LANWSuxv YXLHV2Bc2rrfXV1bcxlsgNMuKBarBTpgl5FtdKRvYSgUS7tPXTpgRUblSpm2Qf35GUxJ PzKCW8IlESVXg3jqhgF+G82x5DzH2hVTc8qnLaHdWsgElmawqqc4nrpzD2ZK9UOskRcj NIrg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1773146988; x=1773751788; 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=IBw8//o/FKk+iSUCDuIRcFnfCH+1hN6m93POT/Oa1kE=; b=FdZgXHczavjRYibHckYM/0tpuD3FDPD0y7bSzgqcZxeSjNkUHgzUNYAZ9Yk2F+Oslv f10mqes2igEZDsuGm11Y7sikB0QCIX6aKXBE06sHg+qHAwreLuddY4E6U+pTPnn5oSXg NdxrxkOR93Nlyxuz/ioN3ZkYobwQ6ZjLOfchguDlJcjsDbY5kJQeA5dFR7pSpfCIni9o qjsrU2Aduvykfd7pidICau5i2kLSSKGfjFajaEvfEF0gW7MEZk5k8ctrfl0u6rudhmg0 aR4cIwTFJGLj78SvnLmu9zuFu2qK3IYh2exVnjV4pzMWqfjopCzDKVw79pXG8BDuvyJF e5Fg== X-Forwarded-Encrypted: i=1; AJvYcCXqTYJHhzso6Agx/ay2FFAozkjGx8oFrvt8mtJBsxXS0Lw7DCMnI4V1ARinN3QXuz4ac8U3hCJ2UcL7Dxc=@vger.kernel.org X-Gm-Message-State: AOJu0YyaHk9XRM1p2wFlZmzCXYUuM9mmk0mCNlH+xYrUEhbNI2GrR0HU iVXfu5+jmvsy0b1yOnTfOBjdFjpD4HDM4XRvKfZZ5MvTzkQQy90+wYbj3UrOqbS91R5lNKxuzST w7UkkfD0rYCFyAo6F+YQAl8koGKBmFQ== X-Received: from wmoo8-n1.prod.google.com ([2002:a05:600d:108:10b0:485:4553:1a97]) (user=sebastianene job=prod-delivery.src-stubby-dispatcher) by 2002:a05:600c:4e4f:b0:485:3f72:323f with SMTP id 5b1f17b1804b1-4853f7233b2mr80282675e9.11.1773146987881; Tue, 10 Mar 2026 05:49:47 -0700 (PDT) Date: Tue, 10 Mar 2026 12:49:24 +0000 In-Reply-To: <20260310124933.830025-1-sebastianene@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260310124933.830025-1-sebastianene@google.com> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog Message-ID: <20260310124933.830025-6-sebastianene@google.com> Subject: [PATCH 05/14] irqchip/gic-v3-its: Prepare shadow structures for KVM host deprivilege From: Sebastian Ene To: alexandru.elisei@arm.com, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, android-kvm@google.com Cc: catalin.marinas@arm.com, dbrazdil@google.com, joey.gouly@arm.com, kees@kernel.org, mark.rutland@arm.com, maz@kernel.org, oupton@kernel.org, perlarsen@google.com, qperret@google.com, rananta@google.com, sebastianene@google.com, smostafa@google.com, suzuki.poulose@arm.com, tabba@google.com, tglx@kernel.org, vdonnefort@google.com, bgrzesik@google.com, will@kernel.org, yuzenghui@huawei.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Expose two helper functions to support emulated ITS in the hypervisor. These allow the KVM layer to notify the driver when hypervisor initialization is complete. The caller is expected to use the functions as follows: 1. its_start_deprivilege(): Acquire the ITS locks. 2. on_each_cpu(_kvm_host_prot_finalize, ...): Finalizes pKVM init 3. its_end_deprivilege(): Shadow the ITS structures, invoke the KVM callback, and release locks. Specifically, this shadows the ITS command queue and the 1st level indirect tables. These shadow buffers will be used by the driver after host deprivilege, while the hypervisor unmaps and takes ownership of the original structures. Signed-off-by: Sebastian Ene --- drivers/irqchip/irq-gic-v3-its.c | 165 +++++++++++++++++++++++++++-- include/linux/irqchip/arm-gic-v3.h | 24 +++++ 2 files changed, 178 insertions(+), 11 deletions(-) diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-= its.c index 291d7668cc8d..278dbc56f962 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -78,17 +78,6 @@ struct its_collection { u16 col_id; }; =20 -/* - * The ITS_BASER structure - contains memory information, cached - * value of BASER register configuration and ITS page size. - */ -struct its_baser { - void *base; - u64 val; - u32 order; - u32 psz; -}; - struct its_device; =20 /* @@ -5232,6 +5221,160 @@ static int __init its_compute_its_list_map(struct i= ts_node *its) return its_number; } =20 +static void its_free_shadow_tables(struct its_shadow_tables *shadow) +{ + int i; + + if (shadow->cmd_shadow) + its_free_pages(shadow->cmd_shadow, get_order(ITS_CMD_QUEUE_SZ)); + + for (i =3D 0; i < GITS_BASER_NR_REGS; i++) { + if (!shadow->tables[i].shadow) + continue; + + its_free_pages(shadow->tables[i].shadow, 0); + } + + its_free_pages(shadow, 0); +} + +static struct its_shadow_tables *its_get_shadow_tables(struct its_node *it= s) +{ + void *page; + struct its_shadow_tables *shadow; + int i; + + page =3D its_alloc_pages_node(its->numa_node, GFP_KERNEL | __GFP_ZERO, 0); + if (!page) + return NULL; + + shadow =3D (void *)page_address(page); + page =3D its_alloc_pages_node(its->numa_node, + GFP_KERNEL | __GFP_ZERO, + get_order(ITS_CMD_QUEUE_SZ)); + if (!page) + goto err_alloc_shadow; + + shadow->cmd_shadow =3D page_address(page); + shadow->cmdq_len =3D ITS_CMD_QUEUE_SZ; + shadow->cmd_original =3D its->cmd_base; + + memcpy(shadow->tables, its->tables, sizeof(struct its_baser) * GITS_BASER= _NR_REGS); + + for (i =3D 0; i < GITS_BASER_NR_REGS; i++) { + if (!(shadow->tables[i].val & GITS_BASER_VALID)) + continue; + + if (!(shadow->tables[i].val & GITS_BASER_INDIRECT)) + continue; + + page =3D its_alloc_pages_node(its->numa_node, + GFP_KERNEL | __GFP_ZERO, + shadow->tables[i].order); + if (!page) + goto err_alloc_shadow; + + shadow->tables[i].shadow =3D page_address(page); + + memcpy(shadow->tables[i].shadow, shadow->tables[i].base, + PAGE_ORDER_TO_SIZE(shadow->tables[i].order)); + } + + return shadow; + +err_alloc_shadow: + its_free_shadow_tables(shadow); + return NULL; +} + +void *its_start_depriviledge(void) +{ + struct its_node *its; + int num_nodes =3D 0, i =3D 0; + unsigned long *flags; + + raw_spin_lock(&its_lock); + list_for_each_entry(its, &its_nodes, entry) { + num_nodes++; + } + + flags =3D kzalloc(num_nodes * sizeof(unsigned long), GFP_KERNEL_ACCOUNT); + if (!flags) { + raw_spin_unlock(&its_lock); + return NULL; + } + + list_for_each_entry(its, &its_nodes, entry) { + raw_spin_lock_irqsave(&its->lock, flags[i++]); + } + + return flags; +} +EXPORT_SYMBOL_GPL(its_start_depriviledge); + +static int its_switch_to_shadow_locked(struct its_node *its, its_init_emul= ate init_emulate_cb) +{ + struct its_shadow_tables *hyp_shadow, shadow; + int i, ret; + u64 baser, baser_phys; + + hyp_shadow =3D its_get_shadow_tables(its); + if (!hyp_shadow) + return -ENOMEM; + + memcpy(&shadow, hyp_shadow, sizeof(shadow)); + ret =3D init_emulate_cb(its->phys_base, hyp_shadow); + if (ret) { + its_free_shadow_tables(hyp_shadow); + return ret; + } + + /* Switch the driver command queue to use the shadow and save the origina= l */ + its->cmd_write =3D (its->cmd_write - its->cmd_base) + + (struct its_cmd_block *)shadow.cmd_shadow; + its->cmd_base =3D shadow.cmd_shadow; + + /* Shadow the first level of the indirect tables */ + for (i =3D 0; i < GITS_BASER_NR_REGS; i++) { + baser =3D shadow.tables[i].val; + + if (!shadow.tables[i].shadow) + continue; + + baser_phys =3D virt_to_phys(shadow.tables[i].shadow); + if (IS_ENABLED(CONFIG_ARM64_64K_PAGES) && (baser_phys >> 48)) + baser_phys =3D GITS_BASER_PHYS_52_to_48(baser_phys); + + its->tables[i].val &=3D ~GENMASK(47, 12); + its->tables[i].val |=3D baser_phys; + its->tables[i].base =3D shadow.tables[i].shadow; + } + + return 0; +} + +int its_end_depriviledge(int ret_pkvm_finalize, unsigned long *flags, its_= init_emulate cb) +{ + struct its_node *its; + int i =3D 0, ret =3D 0; + + if (!flags || !cb) + return -EINVAL; + + list_for_each_entry(its, &its_nodes, entry) { + if (!ret_pkvm_finalize && !ret) + ret =3D its_switch_to_shadow_locked(its, cb); + + raw_spin_unlock_irqrestore(&its->lock, flags[i++]); + } + + kfree(flags); + raw_spin_unlock(&its_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(its_end_depriviledge); + static int __init its_probe_one(struct its_node *its) { u64 baser, tmp; diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm= -gic-v3.h index 0225121f3013..40457a4375d4 100644 --- a/include/linux/irqchip/arm-gic-v3.h +++ b/include/linux/irqchip/arm-gic-v3.h @@ -657,6 +657,30 @@ static inline bool gic_enable_sre(void) return !!(val & ICC_SRE_EL1_SRE); } =20 +/* + * The ITS_BASER structure - contains memory information, cached + * value of BASER register configuration and ITS page size. + */ +struct its_baser { + void *base; + void *shadow; + u64 val; + u32 order; + u32 psz; +}; + +struct its_shadow_tables { + struct its_baser tables[GITS_BASER_NR_REGS]; + void *cmd_shadow; + void *cmd_original; + size_t cmdq_len; +}; + +typedef int (*its_init_emulate)(phys_addr_t its_phys_base, struct its_shad= ow_tables *shadow); + +void *its_start_depriviledge(void); +int its_end_depriviledge(int ret, unsigned long *flags, its_init_emulate c= b); + #endif =20 #endif --=20 2.53.0.473.g4a7958ca14-goog From nobody Thu Apr 9 05:46:32 2026 Received: from mail-ej1-f74.google.com (mail-ej1-f74.google.com [209.85.218.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 EA3E73AD512 for ; Tue, 10 Mar 2026 12:49:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773146992; cv=none; b=uxLohph9wIyuec62Y1OxoWbc8ex8F5yZ2Q8SesBXlNEPS9bi3amlNBM2m671c4QNGDTo/Wy5mv+ony3WbPrcP+puUlpYqeRspQflluSQhUIR/JVGSfdTTnF8+tCdgA6qVZ32pWLVMF9m6fufNa4UIDy8fXeTDLYceOzuAY8xZRU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773146992; c=relaxed/simple; bh=BGZWw0pNpFUVe6fJJOqZpw/0eKKedefH/jfskrr/pLw=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=dS1K+eDkJiJOrw1ltoHkvXIkCZaO6kIg7+v8IOQ9gWSBowdKI33RJJ20atCcpP9MA4LJhilcxBosnn+aN52NuivCe3vtIPlckDeeI3yIY3AMRfWMtbxxn2pfan0+/Da1QR1RFzp2jr9MggC8S8226UmXkxDAYlcKdguIR1txiEE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sebastianene.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=Tfpj+M8P; arc=none smtp.client-ip=209.85.218.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--sebastianene.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="Tfpj+M8P" Received: by mail-ej1-f74.google.com with SMTP id a640c23a62f3a-b96ec4966cbso225337866b.0 for ; Tue, 10 Mar 2026 05:49:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1773146989; x=1773751789; 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=AuLKSluxKmhn480CzigIfSkaIIQucOGgq+FPielHBMw=; b=Tfpj+M8P6SwBW8oR4zT+DrEdpFk8zY9SLqmthesSqZ9TTDrQbWMZhQqRpfUXXVWF/L xgP2ZVmqeoTSzqgTm8AiwF5nkAsqIPWauq1YV80EZK/xqkKPKUKVkC3apLz4i7ybXQaK o2xJADvdpu7IE4+OkGglh9R8e73nXWgHs37Jt+4jAIsHPheSAIsEfqu/ZSecj7eFUIJJ FVHzqlO+Ds+VElTfTEEZjbJjXbXLmfxBZw06wXOKGi2lSa4Q4G3Vf90fKU1yzBsK6NEJ BPNHWyEA0wp5OxQ5zezBBHzhYeHcqRHD/W/fv+2aXj4MiNVirtX/Rzc0QrLvGwOLqLPI 5XUA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1773146989; x=1773751789; 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=AuLKSluxKmhn480CzigIfSkaIIQucOGgq+FPielHBMw=; b=Vg/XKSde0+QLhP85qYZ9U/xsl/BnY9MHffp7cG/jS0tmcCEsriqXOho9wv3NvXBWpN kV85A1YKN1gzOV3PUgwguobGeM6iO36AEb6aX9o48CW1ANEQar//k8edHCBHjh4YJRqQ 8uZdOO3ImToBqEXpogFFOms+Oh1hMu8KgvP0fAq3O9MYqgxXcR+glmfsXfGlZKyLVW9C +qpv5NUir5BayHd54xk0Qo184ZXDaBNpCeh73QCYmWZqxkb4IRXS9/oXihJCCt/ceHQP 0SSy65Xe0tXhsBHGC0dvMUv2CE2pMGpwTkwnxzJqbeCGRk/6pv1WpFMI8siLxK1bvE9x dzCg== X-Forwarded-Encrypted: i=1; AJvYcCV9r6z31UCDDvGVApkVvbQuiNt8he1hM2P0IBUyRl25BxEiLL8EieuZsQTRd7OFm5H1IApGSxkRaXObMjc=@vger.kernel.org X-Gm-Message-State: AOJu0YzpMX80ExIHgOUeBjpBcbPxyRUNoxVMoRKxQcvP1H7bHWgPcZcG 3YCwSdd0eDQJDaTnGq8Bq9WBlOhJsEcVHbO8KNuYWZDRJZxHQgPkZmaFKFkrmDEyXzjid+fnEYh v5MUMJD4W63lBQLIZ3zdNNSY9kWZF4g== X-Received: from edfa4.prod.google.com ([2002:a50:9e84:0:b0:662:810d:badd]) (user=sebastianene job=prod-delivery.src-stubby-dispatcher) by 2002:a17:907:7290:b0:b8e:9a0:1bfb with SMTP id a640c23a62f3a-b942d58ea78mr829388866b.0.1773146989033; Tue, 10 Mar 2026 05:49:49 -0700 (PDT) Date: Tue, 10 Mar 2026 12:49:25 +0000 In-Reply-To: <20260310124933.830025-1-sebastianene@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260310124933.830025-1-sebastianene@google.com> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog Message-ID: <20260310124933.830025-7-sebastianene@google.com> Subject: [PATCH 06/14] KVM: arm64: Add infrastructure for ITS emulation setup From: Sebastian Ene To: alexandru.elisei@arm.com, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, android-kvm@google.com Cc: catalin.marinas@arm.com, dbrazdil@google.com, joey.gouly@arm.com, kees@kernel.org, mark.rutland@arm.com, maz@kernel.org, oupton@kernel.org, perlarsen@google.com, qperret@google.com, rananta@google.com, sebastianene@google.com, smostafa@google.com, suzuki.poulose@arm.com, tabba@google.com, tglx@kernel.org, vdonnefort@google.com, bgrzesik@google.com, will@kernel.org, yuzenghui@huawei.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Share the host command queue with the hypervisor. Donate the original command queue memory to the hypervisor to ensure host exclusion and trap accesses on GITS_CWRITE register. On a CWRITER write, the hypervisor copies commands from the host's queue to the protected queue before updating the hardware register. This ensures the hypervisor mediates all commands sent to the physical ITS. Signed-off-by: Sebastian Ene --- arch/arm64/include/asm/kvm_pkvm.h | 1 + arch/arm64/kvm/hyp/include/nvhe/its_emulate.h | 17 ++ arch/arm64/kvm/hyp/nvhe/its_emulate.c | 203 ++++++++++++++++++ 3 files changed, 221 insertions(+) create mode 100644 arch/arm64/kvm/hyp/include/nvhe/its_emulate.h diff --git a/arch/arm64/include/asm/kvm_pkvm.h b/arch/arm64/include/asm/kvm= _pkvm.h index ef00c1bf7d00..dc5ef2f9ac49 100644 --- a/arch/arm64/include/asm/kvm_pkvm.h +++ b/arch/arm64/include/asm/kvm_pkvm.h @@ -28,6 +28,7 @@ struct pkvm_protected_reg { u64 start_pfn; size_t num_pages; pkvm_emulate_handler *cb; + void *priv; }; =20 extern struct pkvm_protected_reg kvm_nvhe_sym(pkvm_protected_regs)[]; diff --git a/arch/arm64/kvm/hyp/include/nvhe/its_emulate.h b/arch/arm64/kvm= /hyp/include/nvhe/its_emulate.h new file mode 100644 index 000000000000..6be24c723658 --- /dev/null +++ b/arch/arm64/kvm/hyp/include/nvhe/its_emulate.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __NVHE_ITS_EMULATE_H +#define __NVHE_ITS_EMULATE_H + + +#include + + +struct its_shadow_tables; + +int pkvm_init_gic_its_emulation(phys_addr_t dev_addr, void *priv_state, + struct its_shadow_tables *shadow); + +void pkvm_handle_gic_emulation(struct pkvm_protected_reg *region, u64 offs= et, bool write, + u64 *reg, u8 reg_size); +#endif /* __NVHE_ITS_EMULATE_H */ diff --git a/arch/arm64/kvm/hyp/nvhe/its_emulate.c b/arch/arm64/kvm/hyp/nvh= e/its_emulate.c index 0eecbb011898..4a3ccc90a1a9 100644 --- a/arch/arm64/kvm/hyp/nvhe/its_emulate.c +++ b/arch/arm64/kvm/hyp/nvhe/its_emulate.c @@ -1,8 +1,75 @@ // SPDX-License-Identifier: GPL-2.0-only =20 #include +#include +#include #include =20 +struct its_priv_state { + void *base; + void *cmd_hyp_base; + void *cmd_host_base; + void *cmd_host_cwriter; + struct its_shadow_tables *shadow; + hyp_spinlock_t its_lock; +}; + +struct its_handler { + u64 offset; + u8 access_size; + void (*write)(struct its_priv_state *its, u64 offset, u64 value); + void (*read)(struct its_priv_state *its, u64 offset, u64 *read); +}; + +DEFINE_HYP_SPINLOCK(its_setup_lock); + +static void cwriter_write(struct its_priv_state *its, u64 offset, u64 valu= e) +{ + u64 cwriter_offset =3D value & GENMASK(19, 5); + int cmd_len, cmd_offset; + size_t cmdq_sz =3D its->shadow->cmdq_len; + + if (cwriter_offset > cmdq_sz) + return; + + cmd_offset =3D its->cmd_host_cwriter - its->cmd_host_base; + cmd_len =3D cwriter_offset - cmd_offset; + if (cmd_len < 0) + cmd_len =3D cmdq_sz - cmd_offset; + + if (cmd_offset + cmd_len > cmdq_sz) + return; + + memcpy(its->cmd_hyp_base + cmd_offset, its->cmd_host_cwriter, cmd_len); + + its->cmd_host_cwriter =3D its->cmd_host_base + + (cmd_offset + cmd_len) % cmdq_sz; + if (its->cmd_host_cwriter =3D=3D its->cmd_host_base) { + memcpy(its->cmd_hyp_base, its->cmd_host_base, cwriter_offset); + + its->cmd_host_cwriter =3D its->cmd_host_base + cwriter_offset; + } + + writeq_relaxed(value, its->base + GITS_CWRITER); +} + +static void cwriter_read(struct its_priv_state *its, u64 offset, u64 *read) +{ + *read =3D readq_relaxed(its->base + GITS_CWRITER); +} + +#define ITS_HANDLER(off, sz, write_cb, read_cb) \ +{ \ + .offset =3D (off), \ + .access_size =3D (sz), \ + .write =3D (write_cb), \ + .read =3D (read_cb), \ +} + +static struct its_handler its_handlers[] =3D { + ITS_HANDLER(GITS_CWRITER, sizeof(u64), cwriter_write, cwriter_read), + {}, +}; =20 void pkvm_handle_forward_req(struct pkvm_protected_reg *region, u64 offset= , bool write, u64 *reg, u8 reg_size) @@ -21,3 +88,139 @@ void pkvm_handle_forward_req(struct pkvm_protected_reg = *region, u64 offset, bool writeq_relaxed(*reg, addr); } } + +void pkvm_handle_gic_emulation(struct pkvm_protected_reg *region, u64 offs= et, bool write, + u64 *reg, u8 reg_size) +{ + struct its_priv_state *its_priv =3D region->priv; + void __iomem *addr; + struct its_handler *reg_handler; + + if (!its_priv) + return; + + addr =3D its_priv->base + offset; + for (reg_handler =3D its_handlers; reg_handler->access_size; reg_handler+= +) { + if (reg_handler->offset > offset || + reg_handler->offset + reg_handler->access_size <=3D offset) + continue; + + if (reg_handler->access_size & (reg_size - 1)) + continue; + + if (write && reg_handler->write) { + hyp_spin_lock(&its_priv->its_lock); + reg_handler->write(its_priv, offset, *reg); + hyp_spin_unlock(&its_priv->its_lock); + return; + } + + if (!write && reg_handler->read) { + hyp_spin_lock(&its_priv->its_lock); + reg_handler->read(its_priv, offset, reg); + hyp_spin_unlock(&its_priv->its_lock); + return; + } + + return; + } + + pkvm_handle_forward_req(region, offset, write, reg, reg_size); +} + +static struct pkvm_protected_reg *get_region(phys_addr_t dev_addr) +{ + int i; + u64 dev_pfn =3D dev_addr >> PAGE_SHIFT; + + for (i =3D 0; i < PKVM_PROTECTED_REGS_NUM; i++) { + if (pkvm_protected_regs[i].start_pfn =3D=3D dev_pfn) + return &pkvm_protected_regs[i]; + } + + return NULL; +} + +static int pkvm_setup_its_shadow_cmdq(struct its_shadow_tables *shadow) +{ + int ret, i, num_pages; + u64 shadow_start_pfn, original_start_pfn; + void *cmd_shadow_va =3D kern_hyp_va(shadow->cmd_shadow); + + shadow_start_pfn =3D hyp_virt_to_pfn(cmd_shadow_va); + original_start_pfn =3D hyp_virt_to_pfn(kern_hyp_va(shadow->cmd_original)); + num_pages =3D shadow->cmdq_len >> PAGE_SHIFT; + + for (i =3D 0; i < num_pages; i++) { + ret =3D __pkvm_host_share_hyp(shadow_start_pfn + i); + if (ret) + goto unshare_shadow; + } + + ret =3D hyp_pin_shared_mem(cmd_shadow_va, cmd_shadow_va + shadow->cmdq_le= n); + if (ret) + goto unshare_shadow; + + ret =3D __pkvm_host_donate_hyp(original_start_pfn, num_pages); + if (ret) + goto unpin_shadow; + + return ret; + +unpin_shadow: + hyp_unpin_shared_mem(cmd_shadow_va, cmd_shadow_va + shadow->cmdq_len); + +unshare_shadow: + for (i =3D i - 1; i >=3D 0; i--) + __pkvm_host_unshare_hyp(shadow_start_pfn + i); + + return ret; +} + +int pkvm_init_gic_its_emulation(phys_addr_t dev_addr, void *host_priv_stat= e, + struct its_shadow_tables *host_shadow) +{ + int ret; + struct its_priv_state *priv_state =3D kern_hyp_va(host_priv_state); + struct its_shadow_tables *shadow =3D kern_hyp_va(host_shadow); + struct pkvm_protected_reg *its_reg; + + hyp_spin_lock(&its_setup_lock); + its_reg =3D get_region(dev_addr); + if (!its_reg) + return -ENODEV; + + if (its_reg->priv) + return -EOPNOTSUPP; + + ret =3D __pkvm_host_donate_hyp(hyp_virt_to_pfn(priv_state), 1); + if (ret) + return ret; + + ret =3D __pkvm_host_donate_hyp(hyp_virt_to_pfn(shadow), 1); + if (ret) + goto err_with_state; + + ret =3D pkvm_setup_its_shadow_cmdq(shadow); + if (ret) + goto err_with_shadow; + + its_reg->priv =3D priv_state; + + hyp_spin_lock_init(&priv_state->its_lock); + priv_state->shadow =3D shadow; + priv_state->base =3D __hyp_va(dev_addr); + + priv_state->cmd_hyp_base =3D kern_hyp_va(shadow->cmd_original); + priv_state->cmd_host_base =3D kern_hyp_va(shadow->cmd_shadow); + priv_state->cmd_host_cwriter =3D priv_state->cmd_host_base; + + hyp_spin_unlock(&its_setup_lock); + + return 0; +err_with_shadow: + __pkvm_hyp_donate_host(hyp_virt_to_pfn(shadow), 1); +err_with_state: + __pkvm_hyp_donate_host(hyp_virt_to_pfn(priv_state), 1); + return ret; +} --=20 2.53.0.473.g4a7958ca14-goog From nobody Thu Apr 9 05:46:32 2026 Received: from mail-wr1-f73.google.com (mail-wr1-f73.google.com [209.85.221.73]) (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 222103B7B92 for ; Tue, 10 Mar 2026 12:49:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773146993; cv=none; b=lb6FpvpjLUvMJJbdvVCSyjdRQ7BZi43i//iqjmgIQ5QHudyclXDcx3zYuRSqbBqaxvaFl/B0hlJcG2JRUUxILjf5ZyWUSpKngguXF//O8P4be7WH2na+WCBjMQ3NZLdTxyRdQSIh00eSNasziRlTi/Bhe/Sy+YCExKneGdH9/qw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773146993; c=relaxed/simple; bh=4RNc/OGsbdz6eLCOaogz9AGsi/fOhXZQXST7Qa4L1Qg=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=ZbV0bW257rEIFobfMLupZ1D864RXJrJzXjBdgAFN80KzzNKZn6+ixcuhqzZIJNtetIeVME8ChvMM2Kt303oLE+S1TUWx+gpDj3yNakcDfeyJ/ypoe9UWRwmrq/PiZzbvoYc1gorxMLNuP2abadT1w/9wlbsmCwybcx2Bx7coRGM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sebastianene.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=0ZEMEbzB; arc=none smtp.client-ip=209.85.221.73 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--sebastianene.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="0ZEMEbzB" Received: by mail-wr1-f73.google.com with SMTP id ffacd0b85a97d-439b8bc43aeso6934234f8f.1 for ; Tue, 10 Mar 2026 05:49:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1773146990; x=1773751790; 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=DKVeba1O2GNqI9y6nMRgrPtXZ5F94kglcm0NO/0FYK4=; b=0ZEMEbzB2qnPko88r7tv9lvL8/mRk/SzP7IlMbcbFAft2VweCtpAmulYFGSOn4W5cy rXvC0qEGfYIidIbNxuu0Cv7z5C196oammJUhcOQ4z85laDZQaA/zWCDxMnYM6UkpysTf NALazhyqHTRYMQRDNzl5zg+Jb871XKRiUyYQWQoYwtxMackRU3SZyfs6i6ogYptxrVrR S5SxPHwT9pBiu9oFZNzpkI/4Y6Rzz04oAIpZbJojjpjhVzwJy5hfrCck6Pri0nNRXgBv mat0XKnwwASAk6Hv5PjWhTaQjQrvmPgH4fgpAxA01U0aknzAKCVovP11VF8ZF5/G6QEI X9ug== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1773146990; x=1773751790; 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=DKVeba1O2GNqI9y6nMRgrPtXZ5F94kglcm0NO/0FYK4=; b=UjSm2Gvn2B/HblICyGOH/zpc4J46EUXevkRbHC5G2K9a/5Qv5T9ZPGEuaZgSCxdz0Z 0/4Z9n1p2Ckb63sm2lBu8+Y6flSZZCxIYupgp2AGSa+liyqGpf9bfM0BrKqfTZoc4qLv H2aTZx5YF9PwaHlfeamUHyJnNT6E/ECI7K75eQw2MnEx5mXPrUyvQIuYj21JaygeUrMq 2VxpyWhIS9eS+nqhLHDxC4F6vbIdAwfOfA6wdo1Y17bnF0WSXlV32K5ccsC7j9vh7eNS tNnR4yKq3m0Xv+kAq5Ae7hdfKGpZzFUBMwaL0v6oH+7qd0LF3Yxxc/JLkKOAF/Wj9FBm Lr3w== X-Forwarded-Encrypted: i=1; AJvYcCVP7ug4ECKE602iJcsatsl1fOkKQb58ZGtQvN3yRZvWMjKoNssDrsccC8lNHNNkdVpyfZ9t/qs/NR270WU=@vger.kernel.org X-Gm-Message-State: AOJu0Yz/tkcTvFgsuhrLCNvvlUb4upiyl14xTfKZe/RR4uR9ky3U+C2p rZjuEY1EHm0//SFu3BwylHdAdoxAB0a+xa7odgizxVPvqRUXvd/sfWn9MbvY0M1o4piUXn+G2la qGbBAvwB7nWnn7OWClKa89eJzbqmcZw== X-Received: from wrmz10.prod.google.com ([2002:adf:e54a:0:b0:439:b120:9eeb]) (user=sebastianene job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6000:608:b0:439:ad90:389e with SMTP id ffacd0b85a97d-439da8861bdmr24755811f8f.36.1773146990477; Tue, 10 Mar 2026 05:49:50 -0700 (PDT) Date: Tue, 10 Mar 2026 12:49:26 +0000 In-Reply-To: <20260310124933.830025-1-sebastianene@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260310124933.830025-1-sebastianene@google.com> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog Message-ID: <20260310124933.830025-8-sebastianene@google.com> Subject: [PATCH 07/14] KVM: arm64: Restrict host access to the ITS tables From: Sebastian Ene To: alexandru.elisei@arm.com, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, android-kvm@google.com Cc: catalin.marinas@arm.com, dbrazdil@google.com, joey.gouly@arm.com, kees@kernel.org, mark.rutland@arm.com, maz@kernel.org, oupton@kernel.org, perlarsen@google.com, qperret@google.com, rananta@google.com, sebastianene@google.com, smostafa@google.com, suzuki.poulose@arm.com, tabba@google.com, tglx@kernel.org, vdonnefort@google.com, bgrzesik@google.com, will@kernel.org, yuzenghui@huawei.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Setup shadow structures for ITS indirect tables held in the GITS_BASER registers. Make the last level of the Device Table and vPE Table inacessible to the host. In a direct layout configuration, donate the table to the hypervisor since the software is not expected to program them directly. Signed-off-by: Sebastian Ene --- arch/arm64/kvm/hyp/nvhe/its_emulate.c | 143 ++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) diff --git a/arch/arm64/kvm/hyp/nvhe/its_emulate.c b/arch/arm64/kvm/hyp/nvh= e/its_emulate.c index 4a3ccc90a1a9..865a5d6353ed 100644 --- a/arch/arm64/kvm/hyp/nvhe/its_emulate.c +++ b/arch/arm64/kvm/hyp/nvhe/its_emulate.c @@ -141,6 +141,145 @@ static struct pkvm_protected_reg *get_region(phys_add= r_t dev_addr) return NULL; } =20 +static int pkvm_host_unmap_last_level(void *shadow, size_t num_pages, u32 = psz) +{ + u64 *table =3D shadow; + int ret, i, end =3D (num_pages << PAGE_SHIFT) / sizeof(table); + phys_addr_t table_addr; + + for (i =3D 0; i < end; i++) { + if (!(table[i] & GITS_BASER_VALID)) + continue; + + table_addr =3D table[i] & PHYS_MASK; + ret =3D __pkvm_host_donate_hyp(hyp_phys_to_pfn(table_addr), psz >> PAGE_= SHIFT); + if (ret) + goto err_donate; + } + + return 0; +err_donate: + for (i =3D i - 1; i >=3D 0; i--) { + if (!(table[i] & GITS_BASER_VALID)) + continue; + + table_addr =3D table[i] & PHYS_MASK; + __pkvm_hyp_donate_host(hyp_phys_to_pfn(table_addr), psz >> PAGE_SHIFT); + } + return ret; +} + +static int pkvm_share_shadow_table(void *shadow, u64 nr_pages) +{ + u64 i, ret, start_pfn =3D hyp_virt_to_pfn(shadow); + + for (i =3D 0; i < nr_pages; i++) { + ret =3D __pkvm_host_share_hyp(start_pfn + i); + if (ret) + goto unshare; + } + + ret =3D hyp_pin_shared_mem(shadow, shadow + (nr_pages << PAGE_SHIFT)); + if (ret) + goto unshare; + + return ret; +unshare: + for (i =3D i - 1; i >=3D 0; i--) + __pkvm_host_unshare_hyp(start_pfn + i); + return ret; +} + +static void pkvm_unshare_shadow_table(void *shadow, u64 nr_pages) +{ + u64 i, start_pfn =3D hyp_virt_to_pfn(shadow); + + hyp_unpin_shared_mem(shadow, shadow + (nr_pages << PAGE_SHIFT)); + + for (i =3D 0; i < nr_pages; i++) + WARN_ON(__pkvm_host_unshare_hyp(start_pfn + i)); +} + +static void pkvm_host_map_last_level(void *shadow, size_t num_pages, u32 p= sz) +{ + u64 *table; + int i, end =3D (num_pages << PAGE_SHIFT) / sizeof(table); + phys_addr_t table_addr; + + for (i =3D 0; i < end; i++) { + if (!(table[i] & GITS_BASER_VALID)) + continue; + + table_addr =3D table[i] & ~GITS_BASER_VALID; + WARN_ON(__pkvm_hyp_donate_host(hyp_phys_to_pfn(table_addr), psz >> PAGE_= SHIFT)); + } +} + +static int pkvm_setup_its_shadow_baser(struct its_shadow_tables *shadow) +{ + int i, ret; + u64 baser_val, num_pages, type; + void *base, *host_base; + + for (i =3D 0; i < GITS_BASER_NR_REGS; i++) { + baser_val =3D shadow->tables[i].val; + if (!(baser_val & GITS_BASER_VALID)) + continue; + + base =3D kern_hyp_va(shadow->tables[i].base); + num_pages =3D (1 << shadow->tables[i].order); + + ret =3D __pkvm_host_donate_hyp(hyp_virt_to_pfn(base), num_pages); + if (ret) + goto err_donate; + + if (baser_val & GITS_BASER_INDIRECT) { + host_base =3D kern_hyp_va(shadow->tables[i].shadow); + ret =3D pkvm_share_shadow_table(host_base, num_pages); + if (ret) + goto err_with_donation; + + type =3D GITS_BASER_TYPE(baser_val); + if (type =3D=3D GITS_BASER_TYPE_COLLECTION) + continue; + + ret =3D pkvm_host_unmap_last_level(base, num_pages, + shadow->tables[i].psz); + if (ret) + goto err_with_share; + } + } + + return 0; +err_with_share: + pkvm_unshare_shadow_table(host_base, num_pages); +err_with_donation: + __pkvm_hyp_donate_host(hyp_virt_to_pfn(base), num_pages); +err_donate: + for (i =3D i - 1; i >=3D 0; i--) { + baser_val =3D shadow->tables[i].val; + if (!(baser_val & GITS_BASER_VALID)) + continue; + + base =3D kern_hyp_va(shadow->tables[i].base); + num_pages =3D (1 << shadow->tables[i].order); + + WARN_ON(__pkvm_hyp_donate_host(hyp_virt_to_pfn(base), num_pages)); + if (baser_val & GITS_BASER_INDIRECT) { + host_base =3D kern_hyp_va(shadow->tables[i].shadow); + pkvm_unshare_shadow_table(host_base, num_pages); + + type =3D GITS_BASER_TYPE(baser_val); + if (type =3D=3D GITS_BASER_TYPE_COLLECTION) + continue; + + pkvm_host_map_last_level(base, num_pages, shadow->tables[i].psz); + } + } + + return ret; +} + static int pkvm_setup_its_shadow_cmdq(struct its_shadow_tables *shadow) { int ret, i, num_pages; @@ -205,6 +344,10 @@ int pkvm_init_gic_its_emulation(phys_addr_t dev_addr, = void *host_priv_state, if (ret) goto err_with_shadow; =20 + ret =3D pkvm_setup_its_shadow_baser(shadow); + if (ret) + goto err_with_shadow; + its_reg->priv =3D priv_state; =20 hyp_spin_lock_init(&priv_state->its_lock); --=20 2.53.0.473.g4a7958ca14-goog From nobody Thu Apr 9 05:46:32 2026 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 3D8FA3BC674 for ; Tue, 10 Mar 2026 12:49:53 +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=1773146995; cv=none; b=kVeT5D5GTHgng8Bje2P7OwAE03PhloN/HoDe5J0+t8Pu+IfXDlm2CecZBjywFwcfSzWftmlk58HDgvHeuiRKYDkGJwWPMmU3Ca35z467niSdw6LlPeRGRXfSBtP/rmMVTyT2L7WxUNt/tl0UnisUNXuNBtg4TuzlLuOB2pgJ5b8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773146995; c=relaxed/simple; bh=4hJY1N4A2wDueWDi3/QPvsP5ocJDuxsbkmdbVMi1coQ=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=H5rSiCe6PaVV02hgV1lUSkZRqZeEC56Ud2YXn4+BZUX6rR85kLb/o1uovy6UALQ3qbvvNK56ACD9j9MKDr52gINRPs5nRL5v+CEnipoOV7Hzlux0dLyyz7j8vDJ1cw6eD9urFUr7GrzpgPPx0Nnaqo52z4QIqSpP6531jU8aeyQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sebastianene.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=z8ZxjA1o; 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--sebastianene.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="z8ZxjA1o" Received: by mail-wm1-f74.google.com with SMTP id 5b1f17b1804b1-483786a09b1so16872215e9.3 for ; Tue, 10 Mar 2026 05:49:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1773146992; x=1773751792; 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=5FSgXLogofjILU2kyW220LfxF0CifNUwYoLSBdGFOwA=; b=z8ZxjA1oFoApx1t9kuic5Jk/QT09CLTUBqD8eu+VSWuJFsE2LcNbhBcurcKcyIhyDw aaI/5e32drvrs/mDukmDTq9NxN4izHfxqm05ANYBaHsQYaaMFYe6OVvpbmOX/KhS+JSA +1qT5VfiwALLU2Wdg9W2M/AAqG1sAieUq8S1f/Jnqep25gGi54FyOgdBZlD8/j3lMJAu dAN5KG5Jp8XfG0bvrQlLp7Rj3bHfvPJ55lZFbuVV9oAEI1woBrnb6vS97QxD2fMS7AlM ZGTb2AQbxnSRBmTXWc/q8fjci/1/e9K4TN2s4TXp1KsRB82b3tAWL1PaWFK+hwSwVX12 rSlw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1773146992; x=1773751792; 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=5FSgXLogofjILU2kyW220LfxF0CifNUwYoLSBdGFOwA=; b=WMKJ16Bq4+CUyO5MXFTz3vtAEoZwcBGoryLzMIY8oCZy5rpg/xV5gsHC3LYKFBJYgI RBUpY5UAsUT1FjlK71CcnPobsxsC31Kz8aA068201RiBgsCK6Tgo/NRxlmr6utthPW1x JQ5gToyPSJSc6Xtss1PO2BPzAO1Hwu/KlLQTSdQ87Gv/7MXninlayJF9jHgmcV5AJY12 rzKYqpKg0YOQ8s6jkiS+DvZLQt/DbefzCjPw29yAUrkNbFd5vDCr4/N4E7ddOpFPCiaN oDqDXGkLY1Pc5r+g1zRuVvud0OPTYc3rlSWjeCqQSjaHQuoSvqDDU9IsNSevWNXPn0of Aw9g== X-Forwarded-Encrypted: i=1; AJvYcCUA1yXsERCk+0A3vGTPmv9zQFe1/uiWb3fACpoJYmMUWImj+FIxx1Ui1f/cSPryQn8MfCGaF+TgpnEbKus=@vger.kernel.org X-Gm-Message-State: AOJu0YyFIA0GBztaLkOlOPiAaRgR4+rnpkc9hMi3dsXp5WM/BezsJj0K YwHD16Xd8ydhaVSYNHQNOnr7Fc00kC8/Wmx7k5EYHL8H1eDgQdeaibgdtzF3t9CHD3lByelOVx5 rcg7UP1o36TISqwOygXgT97bAOH6BZQ== X-Received: from wmk23.prod.google.com ([2002:a05:600c:297:b0:485:3c21:d5f0]) (user=sebastianene job=prod-delivery.src-stubby-dispatcher) by 2002:a05:600c:4fc4:b0:485:40c6:f51a with SMTP id 5b1f17b1804b1-48540c6f65bmr68470135e9.31.1773146991570; Tue, 10 Mar 2026 05:49:51 -0700 (PDT) Date: Tue, 10 Mar 2026 12:49:27 +0000 In-Reply-To: <20260310124933.830025-1-sebastianene@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260310124933.830025-1-sebastianene@google.com> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog Message-ID: <20260310124933.830025-9-sebastianene@google.com> Subject: [PATCH 08/14] KVM: arm64: Trap & emulate the ITS MAPD command From: Sebastian Ene To: alexandru.elisei@arm.com, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, android-kvm@google.com Cc: catalin.marinas@arm.com, dbrazdil@google.com, joey.gouly@arm.com, kees@kernel.org, mark.rutland@arm.com, maz@kernel.org, oupton@kernel.org, perlarsen@google.com, qperret@google.com, rananta@google.com, sebastianene@google.com, smostafa@google.com, suzuki.poulose@arm.com, tabba@google.com, tglx@kernel.org, vdonnefort@google.com, bgrzesik@google.com, will@kernel.org, yuzenghui@huawei.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Parse the MAPD command and extract the ITT address to sanitize it. When the command has the valid bit set, share the memory that holds the ITT table with the hypervisor to prevent it from being used by someone else and track the pages in an array. When the valid bit is cleared, check if the pages are tracked and then remove the sharing with the hypervisor. Check if we need to do any shadow table updates in case the device table is configured with an indirect layout. Signed-off-by: Sebastian Ene --- arch/arm64/kvm/hyp/nvhe/its_emulate.c | 182 ++++++++++++++++++++++++++ drivers/irqchip/irq-gic-v3-its.c | 12 -- include/linux/irqchip/arm-gic-v3.h | 12 ++ 3 files changed, 194 insertions(+), 12 deletions(-) diff --git a/arch/arm64/kvm/hyp/nvhe/its_emulate.c b/arch/arm64/kvm/hyp/nvh= e/its_emulate.c index 865a5d6353ed..722fe80dc2e5 100644 --- a/arch/arm64/kvm/hyp/nvhe/its_emulate.c +++ b/arch/arm64/kvm/hyp/nvhe/its_emulate.c @@ -12,8 +12,13 @@ struct its_priv_state { void *cmd_host_cwriter; struct its_shadow_tables *shadow; hyp_spinlock_t its_lock; + u16 empty_idx; + u64 tracked_pfns[]; }; =20 +#define MAX_TRACKED_PFNS ((PAGE_SIZE - offsetof(struct its_priv_state, \ + tracked_pfns)) / sizeof(u64)) + struct its_handler { u64 offset; u8 access_size; @@ -23,6 +28,178 @@ struct its_handler { =20 DEFINE_HYP_SPINLOCK(its_setup_lock); =20 +static int track_pfn_add(struct its_priv_state *its, u64 pfn) +{ + int ret, i; + + if (its->empty_idx + 1 >=3D MAX_TRACKED_PFNS) + return -ENOSPC; + + ret =3D __pkvm_host_share_hyp(pfn); + if (ret) + return ret; + + its->tracked_pfns[its->empty_idx] =3D pfn; + for (i =3D 0; i < MAX_TRACKED_PFNS; i++) { + if (!its->tracked_pfns[i]) + break; + } + + its->empty_idx =3D i; + return 0; +} + +static int track_pfn_remove(struct its_priv_state *its, u64 pfn) +{ + int i, ret; + + for (i =3D 0; i < MAX_TRACKED_PFNS; i++) { + if (its->tracked_pfns[i] !=3D pfn) + continue; + + ret =3D __pkvm_host_unshare_hyp(pfn); + if (ret) + return ret; + + its->tracked_pfns[i] =3D 0; + its->empty_idx =3D i; + } + + return 0; +} + +static int get_num_itt_pages(struct its_priv_state *its, u8 num_bits) +{ + int nr_ites =3D 1 << (num_bits + 1); + u64 size, gits_typer =3D readq_relaxed(its->base + GITS_TYPER); + + size =3D nr_ites * (FIELD_GET(GITS_TYPER_ITT_ENTRY_SIZE, gits_typer) + 1); + size =3D max(size, ITS_ITT_ALIGN) + ITS_ITT_ALIGN - 1; + + return PAGE_ALIGN(size) >> PAGE_SHIFT; +} + +static int track_pfn(struct its_priv_state *its, u64 start_pfn, int num_pa= ges, bool remove) +{ + int i, ret; + + for (i =3D 0; i < num_pages; i++) { + if (remove) + ret =3D track_pfn_remove(its, start_pfn + i); + else + ret =3D track_pfn_add(its, start_pfn + i); + + if (ret) + goto err_track; + } + + return 0; +err_track: + for (i =3D i - 1; i >=3D 0; i--) { + if (remove) + track_pfn_add(its, start_pfn + i); + else + track_pfn_remove(its, start_pfn + i); + } + + return ret; +} + +static struct its_baser *get_table(struct its_priv_state *its, u64 type) +{ + int i; + struct its_shadow_tables *shadow =3D its->shadow; + + for (i =3D 0; i < GITS_BASER_NR_REGS; i++) { + if (GITS_BASER_TYPE(shadow->tables[i].val) =3D=3D type) + return &shadow->tables[i]; + } + + return NULL; +} + +static int check_table_update(struct its_priv_state *its, u32 id, u64 type) +{ + u32 lvl1_idx; + u64 esz, *host_table, *hyp_table, new_entry, update; + struct its_baser *table =3D get_table(its, type); + int ret; + phys_addr_t new_lvl2_table, lvl2_table; + + if (!table) + return -EINVAL; + + if (!(table->val & GITS_BASER_INDIRECT)) + return 0; + + esz =3D GITS_BASER_ENTRY_SIZE(table->val); + lvl1_idx =3D id / (table->psz / esz); + + host_table =3D kern_hyp_va(table->shadow); + hyp_table =3D kern_hyp_va(table->base); + + new_entry =3D host_table[id]; + update =3D new_entry ^ hyp_table[id]; + if (!update || !(update & GITS_BASER_VALID)) + return 0; + + new_lvl2_table =3D hyp_phys_to_pfn(new_entry & PHYS_MASK_SHIFT); + lvl2_table =3D hyp_phys_to_pfn(hyp_table[id] & PHYS_MASK_SHIFT); + if (new_entry & GITS_BASER_VALID) + ret =3D __pkvm_host_donate_hyp(new_lvl2_table, table->psz >> PAGE_SHIFT); + else + ret =3D __pkvm_hyp_donate_host(lvl2_table, table->psz >> PAGE_SHIFT); + if (ret) + return ret; + + hyp_table[id] =3D new_entry; + return 0; +} + +static int process_its_mapd(struct its_priv_state *its, struct its_cmd_blo= ck *cmd) +{ + phys_addr_t itt_addr =3D cmd->raw_cmd[2] & GENMASK(51, 8); + u8 size =3D cmd->raw_cmd[1] & GENMASK(4, 0); + bool remove =3D !(cmd->raw_cmd[2] & BIT(63)); + u32 device_id =3D cmd->raw_cmd[0] >> 32; + int num_pages, ret; + u64 base_pfn; + + if (PAGE_ALIGNED(itt_addr)) + return -EINVAL; + + base_pfn =3D hyp_phys_to_pfn(itt_addr); + num_pages =3D get_num_itt_pages(its, size); + + ret =3D check_table_update(its, device_id, GITS_BASER_TYPE_DEVICE); + if (ret) + return ret; + + return track_pfn(its, base_pfn, num_pages, remove); +} + +static int parse_its_cmdq(struct its_priv_state *its, int offset, ssize_t = len) +{ + struct its_cmd_block *cmd =3D its->cmd_hyp_base + offset; + u8 req_type; + int ret =3D 0; + + while (len > 0 && !ret) { + req_type =3D cmd->raw_cmd[0] & GENMASK(7, 0); + + switch (req_type) { + case GITS_CMD_MAPD: + ret =3D process_its_mapd(its, cmd); + break; + } + + cmd++; + len -=3D sizeof(struct its_cmd_block); + } + + return ret; +} + static void cwriter_write(struct its_priv_state *its, u64 offset, u64 valu= e) { u64 cwriter_offset =3D value & GENMASK(19, 5); @@ -41,11 +218,15 @@ static void cwriter_write(struct its_priv_state *its, = u64 offset, u64 value) return; =20 memcpy(its->cmd_hyp_base + cmd_offset, its->cmd_host_cwriter, cmd_len); + if (parse_its_cmdq(its, cmd_offset, cmd_len)) + return; =20 its->cmd_host_cwriter =3D its->cmd_host_base + (cmd_offset + cmd_len) % cmdq_sz; if (its->cmd_host_cwriter =3D=3D its->cmd_host_base) { memcpy(its->cmd_hyp_base, its->cmd_host_base, cwriter_offset); + if (parse_its_cmdq(its, cmd_offset, cmd_len)) + return; =20 its->cmd_host_cwriter =3D its->cmd_host_base + cwriter_offset; } @@ -357,6 +538,7 @@ int pkvm_init_gic_its_emulation(phys_addr_t dev_addr, v= oid *host_priv_state, priv_state->cmd_hyp_base =3D kern_hyp_va(shadow->cmd_original); priv_state->cmd_host_base =3D kern_hyp_va(shadow->cmd_shadow); priv_state->cmd_host_cwriter =3D priv_state->cmd_host_base; + priv_state->empty_idx =3D 0; =20 hyp_spin_unlock(&its_setup_lock); =20 diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-= its.c index 278dbc56f962..be78f7dccb9f 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -121,8 +121,6 @@ static DEFINE_PER_CPU(struct its_node *, local_4_1_its); #define is_v4_1(its) (!!((its)->typer & GITS_TYPER_VMAPP)) #define device_ids(its) (FIELD_GET(GITS_TYPER_DEVBITS, (its)->typer) + 1) =20 -#define ITS_ITT_ALIGN SZ_256 - /* The maximum number of VPEID bits supported by VLPI commands */ #define ITS_MAX_VPEID_BITS \ ({ \ @@ -515,16 +513,6 @@ struct its_cmd_desc { }; }; =20 -/* - * The ITS command block, which is what the ITS actually parses. - */ -struct its_cmd_block { - union { - u64 raw_cmd[4]; - __le64 raw_cmd_le[4]; - }; -}; - #define ITS_CMD_QUEUE_SZ SZ_64K #define ITS_CMD_QUEUE_NR_ENTRIES (ITS_CMD_QUEUE_SZ / sizeof(struct its_cmd= _block)) =20 diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm= -gic-v3.h index 40457a4375d4..4f7d47f3d970 100644 --- a/include/linux/irqchip/arm-gic-v3.h +++ b/include/linux/irqchip/arm-gic-v3.h @@ -612,6 +612,8 @@ */ #define GIC_IRQ_TYPE_LPI 0xa110c8ed =20 +#define ITS_ITT_ALIGN SZ_256 + struct rdists { struct { raw_spinlock_t rd_lock; @@ -634,6 +636,16 @@ struct rdists { bool has_vpend_valid_dirty; }; =20 +/* + * The ITS command block, which is what the ITS actually parses. + */ +struct its_cmd_block { + union { + u64 raw_cmd[4]; + __le64 raw_cmd_le[4]; + }; +}; + struct irq_domain; struct fwnode_handle; int __init its_lpi_memreserve_init(void); --=20 2.53.0.473.g4a7958ca14-goog From nobody Thu Apr 9 05:46:32 2026 Received: from mail-wm1-f73.google.com (mail-wm1-f73.google.com [209.85.128.73]) (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 6E67C3C73E3 for ; Tue, 10 Mar 2026 12:49:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773146995; cv=none; b=aW7qj8YzTXfwDSaOMwgVuv+RextMDHs9aZbIM/JOKgbY7uVLvLyn1sO//Gqwmkf2zrvEKxuITMkswA1vwyuu9tIVKMMzYLd8lm07t6Yux/YbqAV9nMrUPTWhdj3/DXeZwsU0Cp+LjQ8Eh3orfdIDYJRUFO9uLwatTQE97zMR6OM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773146995; c=relaxed/simple; bh=k6UwhIhhsfW0It/EuFgaW+IK3aiuqQqET1Q14sl0QXw=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=FSkuUDWuPx/Y+p+1XjciWxX/no23iUwsClYlQnk3FLjlGAR23YE0WXDRyqqcoXJlo+uRuj2Mu8Hu0ivXwsca3IU1H6OB/DeS/abPT2ng/iqal7ZHLK53Si2j7Sv8Z9c53QnD/OYfS0UDnGLM9GlXPBXQwawLvOVVZUFmDBSFo8c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sebastianene.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=gCQp0/qs; arc=none smtp.client-ip=209.85.128.73 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--sebastianene.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="gCQp0/qs" Received: by mail-wm1-f73.google.com with SMTP id 5b1f17b1804b1-48531e8ae62so17664095e9.3 for ; Tue, 10 Mar 2026 05:49:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1773146993; x=1773751793; 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=jMGGQ3IiwT5PMH1OcoXP65zz2QzMpSJC2ga0AgyGkCg=; b=gCQp0/qsp4/cH8sohZZ8FLILT7JQUjO6h5mCAuKHrBMOXVGIAi+ABNAxPk80qlh40C XpC0DZADLcLbGVLPsahV1fmB1hs7rsuZZmsHwOXlE+6EJxANpO4BzsUEIuGx59JlXPIC ZqXJ0NcxgFJl5eCufrwNqfUrbMGaXhw6yrzly2R+xyCdANR0BTedQB4qUnXlwU7nINqI SG/ZLb+1kLBJnY7hGfpAnhldxmCg5DL1+WPDAxFF0HME82vq6xUW+jrY6qkXo7KuH/QJ GLcc292C1toWMCCo/pISQAlukZsfmK5PIydYycjURcIHuuG7YYlo67BKxwFKNCnRC2e7 KYWA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1773146993; x=1773751793; 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=jMGGQ3IiwT5PMH1OcoXP65zz2QzMpSJC2ga0AgyGkCg=; b=C1to29/NiKHHWQE1/S9rfoZ1FQIKQ+71CkdfNwDNXbXx6YuQ0Aj5+r6jXOzcUse4Vc 64Yl7QioPMzLo4aN6V+OXpfQ07l9NC9olU5j57Zk4pGVopifLsyxVrBMpKtWugXFv708 kX7Pg51Y7Nh3iqRbp6dhrfFbaA3TJ3R8Rb9nVyfJLZecvUl0bJHGYBXkRzJVjKj5v5HH Zbkc6kyraTGUkdCES/fmKgTJn1LRhnGh6W3iEfu0BhuCxJ0kJ3Uvjzdzvzz5pKQW0pEg eS5qzn0LFnpKOg12n0MQTWp6TqBUt/nW6ZwrimOhfwkUNICn+QXfDNswlClYj/2LWL6e 6OJQ== X-Forwarded-Encrypted: i=1; AJvYcCVNBH9EAq8Z0zNHxb0bl7ZJItNCuZZh4l31RoG7WE9BxWtTvwtHflql8EHuc1op54QiH+B0pw11CAyRkVw=@vger.kernel.org X-Gm-Message-State: AOJu0YzCNRIplAau3l7v+6ClcsOciKuLPoJsxLBxnjaxrOn1JtZPmdu2 N3QLawFEGsnyc2FFJyh4IzEKDl/m8tizahr5hKXSsvrDI57lQIyYPyln1EGtHq48cdBkDtY4L3s f3n2QJPwqDykVAiXaPRjZ5hmnFEwuUQ== X-Received: from wmoo8-n1.prod.google.com ([2002:a05:600d:108:10b0:485:4553:1a97]) (user=sebastianene job=prod-delivery.src-stubby-dispatcher) by 2002:a05:600c:6383:b0:485:4526:ee06 with SMTP id 5b1f17b1804b1-4854526fc21mr24095095e9.11.1773146992719; Tue, 10 Mar 2026 05:49:52 -0700 (PDT) Date: Tue, 10 Mar 2026 12:49:28 +0000 In-Reply-To: <20260310124933.830025-1-sebastianene@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260310124933.830025-1-sebastianene@google.com> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog Message-ID: <20260310124933.830025-10-sebastianene@google.com> Subject: [PATCH 09/14] KVM: arm64: Trap & emulate the ITS VMAPP command From: Sebastian Ene To: alexandru.elisei@arm.com, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, android-kvm@google.com Cc: catalin.marinas@arm.com, dbrazdil@google.com, joey.gouly@arm.com, kees@kernel.org, mark.rutland@arm.com, maz@kernel.org, oupton@kernel.org, perlarsen@google.com, qperret@google.com, rananta@google.com, sebastianene@google.com, smostafa@google.com, suzuki.poulose@arm.com, tabba@google.com, tglx@kernel.org, vdonnefort@google.com, bgrzesik@google.com, will@kernel.org, yuzenghui@huawei.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Parse the VMAPP command and extract the virtual pending table address and the size of the table. When the command has the valid bit set, share the memory that holds this table with the hypervisor and track it in an array. Unshare this from the hypervisor when the valid bit is cleared. Check if we need to do any shadow table updates in case the vPE table is configured with an indirect layout. Signed-off-by: Sebastian Ene --- arch/arm64/kvm/hyp/nvhe/its_emulate.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/arch/arm64/kvm/hyp/nvhe/its_emulate.c b/arch/arm64/kvm/hyp/nvh= e/its_emulate.c index 722fe80dc2e5..7049d307a236 100644 --- a/arch/arm64/kvm/hyp/nvhe/its_emulate.c +++ b/arch/arm64/kvm/hyp/nvhe/its_emulate.c @@ -178,6 +178,26 @@ static int process_its_mapd(struct its_priv_state *its= , struct its_cmd_block *cm return track_pfn(its, base_pfn, num_pages, remove); } =20 +static int process_its_vmapp(struct its_priv_state *its, struct its_cmd_bl= ock *cmd) +{ + bool remove =3D !(cmd->raw_cmd[2] & BIT(63)); + phys_addr_t vpt_addr =3D cmd->raw_cmd[3] & GENMASK(51, 16); + u8 vpt_size =3D cmd->raw_cmd[3] & GENMASK(4, 0); + u32 vpe_id =3D (cmd->raw_cmd[1] & GENMASK(47, 32)) >> 32; + int num_pages; + u64 base_pfn; + int ret; + + base_pfn =3D hyp_phys_to_pfn(vpt_addr); + num_pages =3D ALIGN(BIT((vpt_size + 1) >> 3), SZ_64K); + + ret =3D check_table_update(its, vpe_id, GITS_BASER_TYPE_VCPU); + if (ret) + return ret; + + return track_pfn(its, base_pfn, num_pages, remove); +} + static int parse_its_cmdq(struct its_priv_state *its, int offset, ssize_t = len) { struct its_cmd_block *cmd =3D its->cmd_hyp_base + offset; @@ -191,6 +211,10 @@ static int parse_its_cmdq(struct its_priv_state *its, = int offset, ssize_t len) case GITS_CMD_MAPD: ret =3D process_its_mapd(its, cmd); break; + + case GITS_CMD_VMAPP: + ret =3D process_its_vmapp(its, cmd); + break; } =20 cmd++; --=20 2.53.0.473.g4a7958ca14-goog From nobody Thu Apr 9 05:46:32 2026 Received: from mail-wm1-f73.google.com (mail-wm1-f73.google.com [209.85.128.73]) (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 D692A3DC4A2 for ; Tue, 10 Mar 2026 12:49:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773146997; cv=none; b=ew1+kxkms6SuwpB+VUpKfSUEoSnCZhkiKNmm0GqV/I0c/ZxuS+Ri+MWB5DuXhzs9ee8Z+nmb/WMWFtRXfK91cZJFk9t1hfz46Iaep4x/uIRu5e/jKbY5tPLUlHqirsp5Yu2ZMMjCKF8iJiuVYSVV0mYbS0U5jsDYb+zI4iHNPeU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773146997; c=relaxed/simple; bh=FqhVbu0S17LwSG6J6Va7LEFnxXYCF6iCNTZbU4gGMEo=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=aokRjU8eOdhX6pLrug9IGhdmei5vJiBHA7Y1S3UrVufpEjJkvLwe1G8EGDIh7/N/P5HMTN5HEXZcijNkUjXjmYZAf/GNsAp5AnfR0F7NXxM6Vti8Pv+Ub9MDU5RYpd3LwcN0Sxxe4WmFFKsLdT+/TuhY1649xh0UhpyFh5iGG88= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sebastianene.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=PANA8XoE; arc=none smtp.client-ip=209.85.128.73 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--sebastianene.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="PANA8XoE" Received: by mail-wm1-f73.google.com with SMTP id 5b1f17b1804b1-48539bda3dcso20882355e9.2 for ; Tue, 10 Mar 2026 05:49:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1773146994; x=1773751794; 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=cabtoOO69urPXAXi1nwx09QASEtiR2iqFRPNp+1JRfM=; b=PANA8XoEOn0HfmWT00LOPLPaODff48F56xYbRZNi8qlgtIJIHKQhTW9iauciLC7mMi XQX9h/ObrokIulI4PwzfdrlF7/TOgEdn0eiHWjVeIRPkHWT+a4cDECAI6JAT7/PX5tVp jqzxKr3pCFJ9kYIcIn6QB9aFSJaU2P0TsS6mUyvTZGe/YvnupbkMQX2ZEXInMf8yg6fY q8lpfOhvTgBKrYc5dy0e4bZhuaSQr2Frcae8LGuujgqkaP77Zu/N8hVg6ujD7IokOT8g SsYeY4IMEuMVUD0cc/TGzwTJdLcmj7VVcElhPjPW7hr49uD8aGxahQszYJ061nqgaAYU acEQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1773146994; x=1773751794; 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=cabtoOO69urPXAXi1nwx09QASEtiR2iqFRPNp+1JRfM=; b=TcI18pA1yUKryHFJ6cvTi1i7mpTlqrRlacCsyGIuA87xVQ8uuttCW2SCd+bIkhpa03 X13EsjKdtZdykymPYVqz38suQXO7Er74k7c2c5yQPb3k1Qhio6fO0B2qD2GqZlZdthqx PXq/iABRFtzQhEAu9SJDNtgm7Ez60DPEd8No25VkwbW5Wh6IZFluDqBMihNz8NvkdW8E SctX7DId6MunuepkpZKWKL7SNM1w9PVru2PQRPc/38NZTvL8AW1oeb5xrFBF6y80SoKB bSsygFn4Snr65NNFaI5MDM6A1NmMB5awBJQVrAudGzB5GL1zbsqZ0PRRPuYqY5oG6bFt 2toA== X-Forwarded-Encrypted: i=1; AJvYcCVah2XgGat3ok0ucI4kPkMUn5aCRO9uyr/uv5LDtjT5dbhZ42tfyxcQbpI5l9j+lompiXi3pwhY2GEhA5Q=@vger.kernel.org X-Gm-Message-State: AOJu0Yxi2E3TpTKKCP6+l+ludgEu6K52YszUhav/L/20sT6ZtceHZkZ3 J+f3b2hBfMHSjOJP4jtxTvj+VF/WCi/n58ucd7crn5kqHkOeqwSELvfxvW1oyw4dvxCc7FkeiJQ ysUJl2OD9wOSozsMDbvSbmUKEd4Ayjw== X-Received: from wmbjq3.prod.google.com ([2002:a05:600c:55c3:b0:483:6e28:c16f]) (user=sebastianene job=prod-delivery.src-stubby-dispatcher) by 2002:a05:600c:350e:b0:483:3380:ca11 with SMTP id 5b1f17b1804b1-48526978900mr254229025e9.33.1773146994098; Tue, 10 Mar 2026 05:49:54 -0700 (PDT) Date: Tue, 10 Mar 2026 12:49:29 +0000 In-Reply-To: <20260310124933.830025-1-sebastianene@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260310124933.830025-1-sebastianene@google.com> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog Message-ID: <20260310124933.830025-11-sebastianene@google.com> Subject: [PATCH 10/14] KVM: arm64: Trap & emulate the ITS MAPC command From: Sebastian Ene To: alexandru.elisei@arm.com, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, android-kvm@google.com Cc: catalin.marinas@arm.com, dbrazdil@google.com, joey.gouly@arm.com, kees@kernel.org, mark.rutland@arm.com, maz@kernel.org, oupton@kernel.org, perlarsen@google.com, qperret@google.com, rananta@google.com, sebastianene@google.com, smostafa@google.com, suzuki.poulose@arm.com, tabba@google.com, tglx@kernel.org, vdonnefort@google.com, bgrzesik@google.com, will@kernel.org, yuzenghui@huawei.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Parse the MAPC command and verify if we need to do any updates to the shadow if the collection table is configured with an indirect layout. Signed-off-by: Sebastian Ene --- arch/arm64/kvm/hyp/nvhe/its_emulate.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/arm64/kvm/hyp/nvhe/its_emulate.c b/arch/arm64/kvm/hyp/nvh= e/its_emulate.c index 7049d307a236..4782a9a24caa 100644 --- a/arch/arm64/kvm/hyp/nvhe/its_emulate.c +++ b/arch/arm64/kvm/hyp/nvhe/its_emulate.c @@ -198,6 +198,13 @@ static int process_its_vmapp(struct its_priv_state *it= s, struct its_cmd_block *c return track_pfn(its, base_pfn, num_pages, remove); } =20 +static int process_its_mapc(struct its_priv_state *its, struct its_cmd_blo= ck *cmd) +{ + u32 icid =3D cmd->raw_cmd[2] & GENMASK(15, 0); + + return check_table_update(its, icid, GITS_BASER_TYPE_COLLECTION); +} + static int parse_its_cmdq(struct its_priv_state *its, int offset, ssize_t = len) { struct its_cmd_block *cmd =3D its->cmd_hyp_base + offset; @@ -215,6 +222,10 @@ static int parse_its_cmdq(struct its_priv_state *its, = int offset, ssize_t len) case GITS_CMD_VMAPP: ret =3D process_its_vmapp(its, cmd); break; + + case GITS_CMD_MAPC: + ret =3D process_its_mapc(its, cmd); + break; } =20 cmd++; --=20 2.53.0.473.g4a7958ca14-goog From nobody Thu Apr 9 05:46:32 2026 Received: from mail-ed1-f74.google.com (mail-ed1-f74.google.com [209.85.208.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 45C9F3D8912 for ; Tue, 10 Mar 2026 12:49:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773146998; cv=none; b=phdmaQZvBPSYhLYf2v+f/tQkTz66sLkHFXG3wzkUtbwpqqji1jc10PRS10pFgeyIiLXU5Czd//kb4LPaz0QrsOimMQq/IkW7zdRLN9FJ5S/sps8XdalK3IBL2PVyMJNGAsrJ1PwKMEeIeiKLACyZF1jFqzPEiZkF9HfxnLjRXNM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773146998; c=relaxed/simple; bh=LsNi7e8n3RFGuOzyrWgX5uI+Z/GYNBc3tYFBs+03ZZM=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=JHeleHZY2fT4H8ZsHnIZXjZ24YgdRfJpYUyYevx/vf4O+mcTiW2edmvU5BjgoZ1eNjQQEH1w2FpSGMRZvZ1+WWcXMcJEwNWqTytEYzCt5COV2mX4n6vBC6eh5KuAuGjzgH/sSIiIuaQ2b0B7ubB6FDi8xFfc2VSex1FrKv8unPU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sebastianene.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=qOCXypch; arc=none smtp.client-ip=209.85.208.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--sebastianene.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="qOCXypch" Received: by mail-ed1-f74.google.com with SMTP id 4fb4d7f45d1cf-662a61be7a5so1565036a12.3 for ; Tue, 10 Mar 2026 05:49:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1773146996; x=1773751796; 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=6R0MEPExNqGukuDQgEpxXtxN4aPLVf9h/otxBvo9VYk=; b=qOCXypchmSF0PtKC7gXYISxp5Yw6M29bEojg1MLwGSU1U8E4UWDi3Bjkf/Aa0zzy7N DwTiC6gAVign0+9PInmmubcAoko2DXzB+iHSnK0nAdX7f5rPWy1tqO7n8uuS2zEwKr0Z E12fBy3I6eFe+MMqkgqzoyUc+6bW7eDcFBAsbJv8EZxlmmBQxjFcLT03DYD+1UTXEVIs NjtgenoOdx+h5vdZY38eMGht5afq8AjoPMxUNvyVzAJ92GZBsns0Tdy9NBFCyJJdQ2bk gdWzvaNtqEAsW9hTkG3yqy+RxgNcHyVl8kYRBn8PypQxZYOXH5jAH+H7fMH8npa1+uL8 gOOQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1773146996; x=1773751796; 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=6R0MEPExNqGukuDQgEpxXtxN4aPLVf9h/otxBvo9VYk=; b=cW3RcwqDqrqghGgCXS2rpYlKGCizI90E4j90hQzP/8F57bDcBwjRZTH7IlpeGbb7lj xeT8yfjcbQmvUf4hOHjipMEiaXiwODWfPkjzoZnk7TuSeRrUf3kZLG9XL4XZ1qukAyUJ qcK1ZWDwRNcFtKn1yFSPzsK2mHuAjHF1+9nm5ec5FpDtTyjbW22IGH6r89TrDEPPsELx yOBuUHTvi7GgmF/3hZIrvZrG2ZNLsf3YW+71YsyB7Ho7YJNLnTMC1gl6otN39SLDaeTC ZpECcSGXX4BpUn+UXBwx7YRvAXb1hpJ+LB1bCh+gkqt35ZRts6R59A+gRdRy37wdCBzn lnBg== X-Forwarded-Encrypted: i=1; AJvYcCW1PO5ueqUo4wonmv77RxJNql+WC2fLTI5YUXk/J675IUjTZvGy+ZDLZCyigJ8DLfq0bKmIMa+Mjdj6cJs=@vger.kernel.org X-Gm-Message-State: AOJu0YwMkjrL3eUXTz2MLpsJT4CSwIU4uX1Jse5fs5u8GP4cHNsf7o3R T8kQPmxHvW7o854wffCr4bUTb7ssHxCRTvPoMnnfcadVlG3PRqB9EWSzYQaabao4Ns50olGVqz9 YUS9jelT9gt5SxZYzcB0XYbm8mgbDqQ== X-Received: from edtb1.prod.google.com ([2002:aa7:c901:0:b0:662:85d8:35f8]) (user=sebastianene job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6402:1463:b0:662:bd98:890a with SMTP id 4fb4d7f45d1cf-662bd988b1bmr1727440a12.25.1773146995409; Tue, 10 Mar 2026 05:49:55 -0700 (PDT) Date: Tue, 10 Mar 2026 12:49:30 +0000 In-Reply-To: <20260310124933.830025-1-sebastianene@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260310124933.830025-1-sebastianene@google.com> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog Message-ID: <20260310124933.830025-12-sebastianene@google.com> Subject: [PATCH 11/14] KVM: arm64: Restrict host updates to GITS_CTLR From: Sebastian Ene To: alexandru.elisei@arm.com, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, android-kvm@google.com Cc: catalin.marinas@arm.com, dbrazdil@google.com, joey.gouly@arm.com, kees@kernel.org, mark.rutland@arm.com, maz@kernel.org, oupton@kernel.org, perlarsen@google.com, qperret@google.com, rananta@google.com, sebastianene@google.com, smostafa@google.com, suzuki.poulose@arm.com, tabba@google.com, tglx@kernel.org, vdonnefort@google.com, bgrzesik@google.com, will@kernel.org, yuzenghui@huawei.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Prevent unpredictable hardware behavior when the host tries to enable the ITS while it is not in quiescent state. Signed-off-by: Sebastian Ene --- arch/arm64/kvm/hyp/nvhe/its_emulate.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/arch/arm64/kvm/hyp/nvhe/its_emulate.c b/arch/arm64/kvm/hyp/nvh= e/its_emulate.c index 4782a9a24caa..539d2ee3b58e 100644 --- a/arch/arm64/kvm/hyp/nvhe/its_emulate.c +++ b/arch/arm64/kvm/hyp/nvhe/its_emulate.c @@ -274,6 +274,23 @@ static void cwriter_read(struct its_priv_state *its, u= 64 offset, u64 *read) *read =3D readq_relaxed(its->base + GITS_CWRITER); } =20 +static void ctlr_read(struct its_priv_state *its, u64 offset, u64 *read) +{ + *read =3D readq_relaxed(its->base + GITS_CTLR); +} + +static void ctlr_write(struct its_priv_state *its, u64 offset, u64 value) +{ + u64 ctlr =3D readq_relaxed(its->base + GITS_CTLR); + bool is_quiescent =3D !!(ctlr & GITS_CTLR_QUIESCENT); + bool is_enabled =3D !!(ctlr & GITS_CTLR_ENABLE); + + if (!is_enabled && (value & GITS_CTLR_ENABLE) && !is_quiescent) + return; + + writeq_relaxed(value, its->base + GITS_CTLR); +} + #define ITS_HANDLER(off, sz, write_cb, read_cb) \ { \ .offset =3D (off), \ @@ -284,6 +301,7 @@ static void cwriter_read(struct its_priv_state *its, u6= 4 offset, u64 *read) =20 static struct its_handler its_handlers[] =3D { ITS_HANDLER(GITS_CWRITER, sizeof(u64), cwriter_write, cwriter_read), + ITS_HANDLER(GITS_CTLR, sizeof(u64), ctlr_write, ctlr_read), {}, }; =20 --=20 2.53.0.473.g4a7958ca14-goog From nobody Thu Apr 9 05:46:32 2026 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 A1A943EC2F4 for ; Tue, 10 Mar 2026 12:49:58 +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=1773146999; cv=none; b=YPhA7c0J0Afo2z6jLchf7gncwckR3/4wkXn8gFwPzccNWVXn9dwAnhHZ6i2nBJeKzwiY3TpOn2SmuZirI2ZhZsBmxxjfCtboBeln0FqzQtlfcBF1J030MVFXkmTwaIWzjzCGhKIfpEMmjN7qC8bEBcxnAwQXbiCEFjMmIi2EWs4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773146999; c=relaxed/simple; bh=RTITKTt8/00tVHzHX3kJ0PB866gXj1ZVjWj6O0grKkE=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=FVUoB/nE9hWfV1X6aLWljBQy6/3krmK5GdfFwsINIsc7U45x7HJuIuzBVU3HyF8NifdDvnA3M0X6ISUAfccoSZWqRyrLV5pzdBg1Au8EdfFqgRRjJ+Ym2HPaQDFQLjXVqO3QgqCCo7cIOBJYR5EIL5P2MvC4CV5Tt0woFqPrXhE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sebastianene.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=ADoAH4UY; 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--sebastianene.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="ADoAH4UY" Received: by mail-wm1-f74.google.com with SMTP id 5b1f17b1804b1-485345e2fdfso13915725e9.2 for ; Tue, 10 Mar 2026 05:49:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1773146997; x=1773751797; 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=VEWbELOsDpdm123yqs/nC4AQmYY2qHXqVI/qysPxPqQ=; b=ADoAH4UYMb9bn2yzHTvw+8lqaXc7RNwlQ2M6cO4IiV5cYZxFdnX+7k6UT8NH1HSsB8 HxkNaNf3qR98gj+75aRmb/tKbZula+g5BdB1LAlJTn61TqC7vbTEgK6u0lC4vDizSXvH hHSknqHqqYVu8Xi1cj0SrXp8Swee/Ql3NcScPXYeU3cUnz8v6ue9oVwO4a5XlXhhu8xd TP8o2PsX/XCqMrjnfDF9XgYXw2P4T9LDxg7+DzXg4gjLrXhbW1/3qBj6AvsTUakwUJ5Y HfRGgRCwpqdGkBGQXSxavYM81x3eS6tdVRtZeDkPomltcMel93K9730/LM0v0CE/GRBA Pkmg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1773146997; x=1773751797; 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=VEWbELOsDpdm123yqs/nC4AQmYY2qHXqVI/qysPxPqQ=; b=EViKWG4F4AQfLDxOp2mi6dKmRLGuooLNYuZw6G8xLw69e6cx3LnoMa12p3LRao2g4h d+HRNfirVk+WKYKgyoeYFQfQk/9U4jyIAsFqkhh6pZnGY3OML95QoBkydIcCC+6JotuO TU/S7x4O8xdLLDjLeEcBhaClxswKkJzZUTLZYcBdM78lW1xEV1XTP97A7QCk4yxhay1u KGUqFg8CRhyUTNwpySuM2ZfVqYPMr0GeRUsn+ipxKBnQ1dethHPve4ggoiIvgSvAup7E KFnyrTtRi5Q+b/2TrxOmlNG2mT+PVTke8C7/XDZeOtfyF2C3+NT0hbDK/SYaJxl41I+G Gz3w== X-Forwarded-Encrypted: i=1; AJvYcCVL4sbnFnLS1V8TSuOUPEjzPVYqEkKOsHvBEorUJL6J0d8Kc0zIzyggM1uDDeZ9tlvqThUYu2Qmid2FLpU=@vger.kernel.org X-Gm-Message-State: AOJu0Yw57At9pvI+YylOwHqNiwE+++Rtbs7mARNSK4buIA1/kBY0+CBK JVv7SOYvo1P6lW5LBRHsG/GyFb6AMg9V0oLsx7A3PozBJRzhSV7gpRlFrd2gBUmeOOkNFKOb+Ty UdlwswdOXKDMPD/OulWPku6qpNZR/8Q== X-Received: from wmpj41.prod.google.com ([2002:a05:600c:48a9:b0:485:3a2f:2f7e]) (user=sebastianene job=prod-delivery.src-stubby-dispatcher) by 2002:a05:600c:46cb:b0:485:3dfc:57c with SMTP id 5b1f17b1804b1-4853dfc073cmr92510315e9.21.1773146996957; Tue, 10 Mar 2026 05:49:56 -0700 (PDT) Date: Tue, 10 Mar 2026 12:49:31 +0000 In-Reply-To: <20260310124933.830025-1-sebastianene@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260310124933.830025-1-sebastianene@google.com> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog Message-ID: <20260310124933.830025-13-sebastianene@google.com> Subject: [PATCH 12/14] KVM: arm64: Restrict host updates to GITS_CBASER From: Sebastian Ene To: alexandru.elisei@arm.com, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, android-kvm@google.com Cc: catalin.marinas@arm.com, dbrazdil@google.com, joey.gouly@arm.com, kees@kernel.org, mark.rutland@arm.com, maz@kernel.org, oupton@kernel.org, perlarsen@google.com, qperret@google.com, rananta@google.com, sebastianene@google.com, smostafa@google.com, suzuki.poulose@arm.com, tabba@google.com, tglx@kernel.org, vdonnefort@google.com, bgrzesik@google.com, will@kernel.org, yuzenghui@huawei.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Prevent the host from updating the ITS command queue base address (GITS_CBASER) while the ITS is enabled or not in a quiescent state. This enforcement prevents unpredictable hardware behavior and ensures the host cannot update the hardware with a new queue address behind the hypervisor's back, which would bypass the command queue shadowing mechanism. Signed-off-by: Sebastian Ene --- arch/arm64/kvm/hyp/nvhe/its_emulate.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/arch/arm64/kvm/hyp/nvhe/its_emulate.c b/arch/arm64/kvm/hyp/nvh= e/its_emulate.c index 539d2ee3b58e..9715f15cd432 100644 --- a/arch/arm64/kvm/hyp/nvhe/its_emulate.c +++ b/arch/arm64/kvm/hyp/nvhe/its_emulate.c @@ -291,6 +291,30 @@ static void ctlr_write(struct its_priv_state *its, u64= offset, u64 value) writeq_relaxed(value, its->base + GITS_CTLR); } =20 +static void cbaser_write(struct its_priv_state *its, u64 offset, u64 value) +{ + u64 ctlr =3D readq_relaxed(its->base + GITS_CTLR); + int num_pages; + + if ((ctlr & GITS_CTLR_ENABLE) || + !(ctlr & GITS_CTLR_QUIESCENT)) + return; + + num_pages =3D its->shadow->cmdq_len / SZ_4K; + value &=3D ~GENMASK(7, 0) | ~GENMASK_ULL(51, 12); + + value |=3D (num_pages - 1) & GENMASK(7, 0); + value |=3D __hyp_pa(its->cmd_hyp_base) & GENMASK_ULL(51, 12); + + its->cmd_host_cwriter =3D its->cmd_host_base; + writeq_relaxed(value, its->base + GITS_CBASER); +} + +static void cbaser_read(struct its_priv_state *its, u64 offset, u64 *read) +{ + *read =3D readq_relaxed(its->base + GITS_CBASER); +} + #define ITS_HANDLER(off, sz, write_cb, read_cb) \ { \ .offset =3D (off), \ @@ -302,6 +326,7 @@ static void ctlr_write(struct its_priv_state *its, u64 = offset, u64 value) static struct its_handler its_handlers[] =3D { ITS_HANDLER(GITS_CWRITER, sizeof(u64), cwriter_write, cwriter_read), ITS_HANDLER(GITS_CTLR, sizeof(u64), ctlr_write, ctlr_read), + ITS_HANDLER(GITS_CBASER, sizeof(u64), cbaser_write, cbaser_read), {}, }; =20 --=20 2.53.0.473.g4a7958ca14-goog From nobody Thu Apr 9 05:46:32 2026 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 982CA3EE1C3 for ; Tue, 10 Mar 2026 12:49:59 +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=1773147000; cv=none; b=cp8rqSZTY4rcBJI5skNl/6NXgpqwVqhL+5RYiuMjkS9nKuOepJOrMbWjsUlIaIyg/9UJ+F5zn8vcYG81N5f3DUwZ1cZtLxOrtR8MBcP0r+f1iViRfRQm6lq6WwBD6p4/wRXVdB5aQollL3F3AF7TX6uDvIHMPszJe7aceeu3pgc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773147000; c=relaxed/simple; bh=dQXB6lQBS0QKJpL+HhStZfpp+h+pcXSATbZcztl2TJk=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=Qip0b7ZTUrztEaL/Cfm6RdmGFv/KegWuHgPisZmkiWRClN/ShLuzmzfVyou9qb68aTxbyN1ij0wrcjlpB6GM68SD7Eve7NXfE3Y7GsHNmsq21P4OzmO6nJ/Ozqbkvd4d3soiOGO7Sf75YbAYLY5TPXR1BHT1oQsOP9K3nAE8VDA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sebastianene.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=GwX4sqWQ; 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--sebastianene.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="GwX4sqWQ" Received: by mail-wm1-f74.google.com with SMTP id 5b1f17b1804b1-4853b00f9f5so17898085e9.2 for ; Tue, 10 Mar 2026 05:49:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1773146998; x=1773751798; 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=ok3Trxc1drhi1LSuLE9o9e58C6eJmakQglQiNgbjypE=; b=GwX4sqWQd3r0zmd6yeLBTi1cCOFGJC55fMRl7xVuStR4bB5YhmItBj3+89cDklAmqR zr4vTKeF/6u+dZQ7VVFTW2TZlzxAlNEwAABtRmPXJFnwCy3aNV+fJFI7VWR9xsFSisjf HZZbe/rkWVNx89rc9u0WvFBeoorfj3DCePCtylRtnxBOg5KltfxJxaL8jHjkPfk6ZLH5 8gXKplv5SN/QSCRiGrMFvF36WtOq7ysP/NmO2dfARYcpkkuUukTl7yWCt6qfg+aPmpY2 hb7Ky+c2NDPGIYt6LHwEovMCgGKyESOv0UTmc3U5AJUJmKPqWnk00W1Hl3xATBjcc/js ypHA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1773146998; x=1773751798; 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=ok3Trxc1drhi1LSuLE9o9e58C6eJmakQglQiNgbjypE=; b=cxmxiBH7Wc2lKchbbsNmj2QIgHNfOTgAyryM/SuLpOIldktTZNSK1B0c7iZrIcMd8R W1CTBEYwSpBKnKuZKIsukf9vmMdXDEVGtJ9Rom36z5wBezLJj5Af/ieaWXLkcfZ7aWIC OOCNbhj4dwTRyczEZhwMwXxGk/FI9qvVrbbvwDPyJu58GavkR0UCHwYwMm6AlqtPIupg tgQpEeUSvIM+1LwRzvVgRE/AZu0BuxMMvlUqlTs6V7nPfWhPtJo/gb93vVAVUZsbDPLJ Wp2HHoJ3I0dcSgMLJBn6nUJKw5OVLJgtC6wxQGLNucethQwKkuVgwdweWDNzn932Gdht lckA== X-Forwarded-Encrypted: i=1; AJvYcCVZ0kfJHHBnbfKU/f7IfiCNoaLFGQ5p8g0bFEPjPGCV/uJcvhTuCXGyr/Km4AHe68gAPeu0nvlHgZjMwn0=@vger.kernel.org X-Gm-Message-State: AOJu0Ywi/RR9B571PwCrr6RZE/5Dx+wrDI3CmRsevnXC61WJvQB7AGbc uS99jlwm2LYa1RqmD0wl7wU0t7UJocUXtxfDM7+LYUeRZU4XRUQK0stZLyVC66Nm5ySZPF3Kuhc VqDqAWxVU2eg48EXOYnTR6j85ZZsq5g== X-Received: from wrbeh2.prod.google.com ([2002:a05:6000:4102:b0:439:e77e:e4b4]) (user=sebastianene job=prod-delivery.src-stubby-dispatcher) by 2002:a05:600c:8708:b0:485:3a03:ceca with SMTP id 5b1f17b1804b1-4853c39afc4mr90731285e9.23.1773146998009; Tue, 10 Mar 2026 05:49:58 -0700 (PDT) Date: Tue, 10 Mar 2026 12:49:32 +0000 In-Reply-To: <20260310124933.830025-1-sebastianene@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260310124933.830025-1-sebastianene@google.com> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog Message-ID: <20260310124933.830025-14-sebastianene@google.com> Subject: [PATCH 13/14] KVM: arm64: Restrict host updates to GITS_BASER From: Sebastian Ene To: alexandru.elisei@arm.com, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, android-kvm@google.com Cc: catalin.marinas@arm.com, dbrazdil@google.com, joey.gouly@arm.com, kees@kernel.org, mark.rutland@arm.com, maz@kernel.org, oupton@kernel.org, perlarsen@google.com, qperret@google.com, rananta@google.com, sebastianene@google.com, smostafa@google.com, suzuki.poulose@arm.com, tabba@google.com, tglx@kernel.org, vdonnefort@google.com, bgrzesik@google.com, will@kernel.org, yuzenghui@huawei.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Prevent the host from updating the ITS tables while the ITS is enabled and the tables are already set. This enforcement prevents unpredictable hardware behavior and ensures the host cannot update the hardware with an unverified table address or size or change its layout. Signed-off-by: Sebastian Ene --- arch/arm64/kvm/hyp/nvhe/its_emulate.c | 45 +++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 6 deletions(-) diff --git a/arch/arm64/kvm/hyp/nvhe/its_emulate.c b/arch/arm64/kvm/hyp/nvh= e/its_emulate.c index 9715f15cd432..e4136a4a2ecb 100644 --- a/arch/arm64/kvm/hyp/nvhe/its_emulate.c +++ b/arch/arm64/kvm/hyp/nvhe/its_emulate.c @@ -22,6 +22,7 @@ struct its_priv_state { struct its_handler { u64 offset; u8 access_size; + u8 num_registers; void (*write)(struct its_priv_state *its, u64 offset, u64 value); void (*read)(struct its_priv_state *its, u64 offset, u64 *read); }; @@ -315,18 +316,48 @@ static void cbaser_read(struct its_priv_state *its, u= 64 offset, u64 *read) *read =3D readq_relaxed(its->base + GITS_CBASER); } =20 -#define ITS_HANDLER(off, sz, write_cb, read_cb) \ +static void baser_write(struct its_priv_state *its, u64 offset, u64 value) +{ + u64 baser, ctlr =3D readq_relaxed(its->base + GITS_CTLR); + int baser_idx; + + if ((ctlr & GITS_CTLR_ENABLE) || + !(ctlr & GITS_CTLR_QUIESCENT)) + return; + + baser_idx =3D (offset - GITS_BASER) >> 3; + baser =3D its->shadow->tables[baser_idx].val; + if ((value & GITS_BASER_INDIRECT) !=3D (baser & GITS_BASER_INDIRECT)) + return; + + value &=3D ~GENMASK(47, 12) | ~GENMASK(9, 0); + value |=3D (baser & GENMASK(47, 12)) | (baser & GENMASK(9, 0)); + + writeq_relaxed(value, its->base + offset); +} + +static void baser_read(struct its_priv_state *its, u64 offset, u64 *read) +{ + *read =3D readq_relaxed(its->base + offset); +} + +#define ITS_HANDLER(off, sz, num, write_cb, read_cb) \ { \ .offset =3D (off), \ .access_size =3D (sz), \ + .num_registers =3D (num), \ .write =3D (write_cb), \ .read =3D (read_cb), \ } =20 +#define ITS_REG(off, sz, write_cb, read_cb) \ + ITS_HANDLER(off, sz, 1, write_cb, read_cb) + static struct its_handler its_handlers[] =3D { - ITS_HANDLER(GITS_CWRITER, sizeof(u64), cwriter_write, cwriter_read), - ITS_HANDLER(GITS_CTLR, sizeof(u64), ctlr_write, ctlr_read), - ITS_HANDLER(GITS_CBASER, sizeof(u64), cbaser_write, cbaser_read), + ITS_REG(GITS_CWRITER, sizeof(u64), cwriter_write, cwriter_read), + ITS_REG(GITS_CTLR, sizeof(u64), ctlr_write, ctlr_read), + ITS_REG(GITS_CBASER, sizeof(u64), cbaser_write, cbaser_read), + ITS_HANDLER(GITS_BASER, sizeof(u64), 8, baser_write, baser_read), {}, }; =20 @@ -354,14 +385,16 @@ void pkvm_handle_gic_emulation(struct pkvm_protected_= reg *region, u64 offset, bo struct its_priv_state *its_priv =3D region->priv; void __iomem *addr; struct its_handler *reg_handler; + u64 end; =20 if (!its_priv) return; =20 addr =3D its_priv->base + offset; for (reg_handler =3D its_handlers; reg_handler->access_size; reg_handler+= +) { - if (reg_handler->offset > offset || - reg_handler->offset + reg_handler->access_size <=3D offset) + end =3D reg_handler->offset + reg_handler->access_size * reg_handler->nu= m_registers; + + if (reg_handler->offset > offset || end <=3D offset) continue; =20 if (reg_handler->access_size & (reg_size - 1)) --=20 2.53.0.473.g4a7958ca14-goog From nobody Thu Apr 9 05:46:32 2026 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 9CBA33D9DA2 for ; Tue, 10 Mar 2026 12:50:00 +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=1773147002; cv=none; b=hNJy61BAv9Sg3b5X4c/7P/mRlNwqHzzrGJKNQrYeUEcDEEkgYwUrgHp8GSigELserDl8GKsrP9GJ+tkWUTHpYb3t0kOZPyrjiTPESVn4hS9S7RF2Q51s17jIt6GO341c7jmz0KmYWak50k3Bd8wB6bvYd4CI7W0v1gysIyanZGc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773147002; c=relaxed/simple; bh=63KweO9P+FBqDWP+uz4wXBFXl+Gx6XDUn+f16gacMkw=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=UxILVcCymU6xT3CuDuU4ic2E56N+XsIDv8jsuASUvYM4l/ZHhxrvIgIZICJKUHgw/8XFZeLM4wGWRJg09MAKIs4tU7nB1+B0fboTqivKbbRLLHBMEYw7RvZoLSyfSQLq2OX8l/eR74uv+M669f13uYMuA3bYybhJMBU5ybWHvNo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--sebastianene.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=ysEwes69; 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--sebastianene.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="ysEwes69" Received: by mail-wm1-f74.google.com with SMTP id 5b1f17b1804b1-485390246c8so25977805e9.0 for ; Tue, 10 Mar 2026 05:50:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1773146999; x=1773751799; 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=Mh5fFUja/4mDlRa8xj9RozoLiOFoKZimG1GpvA9+1Yc=; b=ysEwes69CEkdVBtajxm/3DJYZjDEjmwsAi1dD/p4Y3Ed0HdlbnWF3elT4U//7aRDTJ ohw7uIlusz7gF2HPiujp8CMm1aYLr1m+6TQ1hB3RPkBbkEnYPKxPUypf6m9066g3a4Cx jNiT0e+A8Gjs2+KSYJdnNeSXzihdKKKqGKIwu1N/jCwRJ7L1aPzkDwf3zapT1jmkCWEh JfpXEbNm9NC5GIfSvATNp+1P5OUh0XImFv8Km8SwhzjeowKqXy49HlbXnnLlWZpwNM/a mFYWCe3E9K88f8nQiQlJUf3CGbm9yKVvdO/iaBhsyjo2cLin2+9rzn8aVf2N+pbNH8cK oVrA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1773146999; x=1773751799; 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=Mh5fFUja/4mDlRa8xj9RozoLiOFoKZimG1GpvA9+1Yc=; b=Cota4bRuegW745OnRCDCFH2x/rVX/7VSFPKkuYWWdTyvRvBLtdVFC+JS0ZgBoZx14x SqopEfSgN/7Z5bPvcj6HRVfTuSzeMJXuakbCKPQ5Ho5JUtv0PKBicABLMCoznN1Tss4s cQ4FguE/4zNzJBX3/NUVrs+0y6zVxwEypO+R9PKbQpb6y9mv3QH7McInS9+y5mr9eqx+ uY5vKqBpePaY1smlSaqD0ehP9BbKGj9WBzGOjmo5dbLmkh/wq8/iYgHcPhBwo69Ex8f7 dQ3JbsNuoh1JZk560Tz7OCqZulKnWv6sQlGhgy2LX3rXcJLlnjw6Ga/UZwrLXDDdpBap +O4w== X-Forwarded-Encrypted: i=1; AJvYcCUj+aqqSWkeEyNCKDOEPu3czVgnA4qREx9O8C3l5o53yXzY25MCoxcufuY/kkqMFUta2cXKQYbrFPxijP8=@vger.kernel.org X-Gm-Message-State: AOJu0YwjC67geHGo4wyLrYvmngsthcZN4LKH2suQt1D+GCf1pOA18+mx uukweTbNyU7wv0dsQuC3I3cZTRVpU1m6wT+qlAsQAc681p+KfAwYc4oGMgFgFbLLvdqcNSV9N64 QfopwRyVRBIYUB1rO8sYV3b/OM59gwg== X-Received: from wmqy3.prod.google.com ([2002:a05:600c:3643:b0:482:ef72:5793]) (user=sebastianene job=prod-delivery.src-stubby-dispatcher) by 2002:a05:600c:4445:b0:483:a27e:6706 with SMTP id 5b1f17b1804b1-48526922533mr269324465e9.9.1773146999106; Tue, 10 Mar 2026 05:49:59 -0700 (PDT) Date: Tue, 10 Mar 2026 12:49:33 +0000 In-Reply-To: <20260310124933.830025-1-sebastianene@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260310124933.830025-1-sebastianene@google.com> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog Message-ID: <20260310124933.830025-15-sebastianene@google.com> Subject: [PATCH 14/14] KVM: arm64: Implement HVC interface for ITS emulation setup From: Sebastian Ene To: alexandru.elisei@arm.com, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, android-kvm@google.com Cc: catalin.marinas@arm.com, dbrazdil@google.com, joey.gouly@arm.com, kees@kernel.org, mark.rutland@arm.com, maz@kernel.org, oupton@kernel.org, perlarsen@google.com, qperret@google.com, rananta@google.com, sebastianene@google.com, smostafa@google.com, suzuki.poulose@arm.com, tabba@google.com, tglx@kernel.org, vdonnefort@google.com, bgrzesik@google.com, will@kernel.org, yuzenghui@huawei.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Introduce a new HVC to allow the host to trigger the ITS emulation setup. This interface notifies the ITS driver that hypervisor initialization is complete. Upon invocation, the hypervisor replaces the initial "trap-and-forward" MMIO handler with a full-featured emulation handler. This transition enables mediated access to the ITS hardware, enforcing the verifications required for a protected hypervisor environment. Signed-off-by: Sebastian Ene --- arch/arm64/include/asm/kvm_asm.h | 1 + arch/arm64/include/asm/kvm_pkvm.h | 3 ++- arch/arm64/kvm/hyp/nvhe/hyp-main.c | 14 ++++++++++++++ arch/arm64/kvm/pkvm.c | 24 +++++++++++++++++++++++- 4 files changed, 40 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_= asm.h index a1ad12c72ebf..550dafee88ef 100644 --- a/arch/arm64/include/asm/kvm_asm.h +++ b/arch/arm64/include/asm/kvm_asm.h @@ -89,6 +89,7 @@ enum __kvm_host_smccc_func { __KVM_HOST_SMCCC_FUNC___pkvm_vcpu_load, __KVM_HOST_SMCCC_FUNC___pkvm_vcpu_put, __KVM_HOST_SMCCC_FUNC___pkvm_tlb_flush_vmid, + __KVM_HOST_SMCCC_FUNC___pkvm_init_its_emulation, }; =20 #define DECLARE_KVM_VHE_SYM(sym) extern char sym[] diff --git a/arch/arm64/include/asm/kvm_pkvm.h b/arch/arm64/include/asm/kvm= _pkvm.h index dc5ef2f9ac49..20fb2678a9b9 100644 --- a/arch/arm64/include/asm/kvm_pkvm.h +++ b/arch/arm64/include/asm/kvm_pkvm.h @@ -35,7 +35,8 @@ extern struct pkvm_protected_reg kvm_nvhe_sym(pkvm_protec= ted_regs)[]; extern unsigned int kvm_nvhe_sym(num_protected_reg); extern void kvm_nvhe_sym(pkvm_handle_forward_req)(struct pkvm_protected_re= g *region, u64 offset, bool write, u64 *reg, u8 reg_size); - +extern void kvm_nvhe_sym(pkvm_handle_gic_emulation)(struct pkvm_protected_= reg *region, u64 offset, + bool write, u64 *reg, u8 reg_size); int pkvm_init_host_vm(struct kvm *kvm); int pkvm_create_hyp_vm(struct kvm *kvm); bool pkvm_hyp_vm_is_created(struct kvm *kvm); diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/h= yp-main.c index e7790097db93..4e58e24a1eed 100644 --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c @@ -14,6 +14,7 @@ #include #include =20 +#include #include #include #include @@ -421,6 +422,18 @@ static void handle___kvm_tlb_flush_vmid(struct kvm_cpu= _context *host_ctxt) __kvm_tlb_flush_vmid(kern_hyp_va(mmu)); } =20 +static void handle___pkvm_init_its_emulation(struct kvm_cpu_context *host_= ctxt) +{ + DECLARE_REG(phys_addr_t, dev_addr, host_ctxt, 1); + DECLARE_REG(void *, its_state, host_ctxt, 2); + DECLARE_REG(struct its_shadow_tables *, shadow, host_ctxt, 3); + + if (!is_protected_kvm_enabled()) + return; + + cpu_reg(host_ctxt, 1) =3D pkvm_init_gic_its_emulation(dev_addr, its_state= , shadow); +} + static void handle___pkvm_tlb_flush_vmid(struct kvm_cpu_context *host_ctxt) { DECLARE_REG(pkvm_handle_t, handle, host_ctxt, 1); @@ -630,6 +643,7 @@ static const hcall_t host_hcall[] =3D { HANDLE_FUNC(__pkvm_vcpu_load), HANDLE_FUNC(__pkvm_vcpu_put), HANDLE_FUNC(__pkvm_tlb_flush_vmid), + HANDLE_FUNC(__pkvm_init_its_emulation), }; =20 static void handle_host_hcall(struct kvm_cpu_context *host_ctxt) diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c index a766be6de735..5399998d5235 100644 --- a/arch/arm64/kvm/pkvm.c +++ b/arch/arm64/kvm/pkvm.c @@ -6,6 +6,7 @@ =20 #include #include +#include #include #include #include @@ -62,7 +63,7 @@ static int __init register_protected_regions(void) =20 pkvm_protected_regs[i].start_pfn =3D res.start >> PAGE_SHIFT; pkvm_protected_regs[i].num_pages =3D resource_size(&res) >> PAGE_SHIFT; - pkvm_protected_regs[i].cb =3D lm_alias(&kvm_nvhe_sym(pkvm_handle_forward= _req)); + pkvm_protected_regs[i].cb =3D lm_alias(&kvm_nvhe_sym(pkvm_handle_gic_emu= lation)); i++; } =20 @@ -286,16 +287,37 @@ static void __init _kvm_host_prot_finalize(void *arg) WRITE_ONCE(*err, -EINVAL); } =20 +static int pkvm_init_its_emulation(phys_addr_t dev_addr, struct its_shadow= _tables *shadow) +{ + void *its_state; + int ret; + + its_state =3D (void *)__get_free_page(GFP_KERNEL_ACCOUNT); + if (!its_state) + return -ENOMEM; + + ret =3D kvm_call_hyp_nvhe(__pkvm_init_its_emulation, dev_addr, its_state,= shadow); + if (ret) + free_page((unsigned long)its_state); + + return ret; +} + static int __init pkvm_drop_host_privileges(void) { int ret =3D 0; + void *flags; =20 /* * Flip the static key upfront as that may no longer be possible * once the host stage 2 is installed. */ static_branch_enable(&kvm_protected_mode_initialized); + + flags =3D its_start_depriviledge(); on_each_cpu(_kvm_host_prot_finalize, &ret, 1); + its_end_depriviledge(ret, flags, &pkvm_init_its_emulation); + return ret; } =20 --=20 2.53.0.473.g4a7958ca14-goog