From: Sebastian Ene <sebastianene@google.com>
To: catalin.marinas@arm.com, fuad.tabba@linux.dev,
joey.gouly@arm.com, mark.rutland@arm.com, maz@kernel.org,
oupton@kernel.org, rananta@google.com, Sascha.Bischoff@arm.com,
suzuki.poulose@arm.com, will@kernel.org
Cc: kvmarm@lists.linux.dev, android-kvm@google.com,
bgrzesik@google.com, linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, nathan@kernel.org,
perlarsen@google.com, sebastianene@google.com,
seiden@linux.ibm.com, smostafa@google.com, tglx@kernel.org,
vdonnefort@google.com, vladimir.murzin@arm.com,
yuzenghui@huawei.com, zenghui.yu@linux.dev
Subject: [PATCH v2 13/13] KVM: arm64: Implement HVC interface for ITS emulation setup
Date: Fri, 7 Aug 2026 16:43:23 +0000 [thread overview]
Message-ID: <20260807164322.2970811-15-sebastianene@google.com> (raw)
In-Reply-To: <20260807164322.2970811-2-sebastianene@google.com>
Introduce a new HVC to allow the host to trigger the ITS emulation
setup. Use the introduced API in the GIC ITS driver to call the driver
to lock the ITS before pKVM finalize and to prepare for emulation setup.
On the return path from the pKVM finalize, call into the driver to
release the ITS locks which performs a switch in the driver to use a
different command queue and a different set of level-1 indirect tables.
Allocate memory that will be used by the emulation to track the internal
state and send the snapshot state from the driver.
Replace the initial "trap-and-forward" MMIO handler with a full-featured
emulation handler.
Signed-off-by: Sebastian Ene <sebastianene@google.com>
---
arch/arm64/include/asm/kvm_asm.h | 1 +
arch/arm64/include/asm/kvm_pkvm.h | 4 ++--
arch/arm64/kvm/hyp/nvhe/hyp-main.c | 16 ++++++++++++++++
arch/arm64/kvm/hyp/nvhe/its_emulate.c | 4 ++--
arch/arm64/kvm/pkvm.c | 26 ++++++++++++++++++++++++--
5 files changed, 45 insertions(+), 6 deletions(-)
diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
index 043495f7fc78..fcb2871b8a86 100644
--- a/arch/arm64/include/asm/kvm_asm.h
+++ b/arch/arm64/include/asm/kvm_asm.h
@@ -114,6 +114,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_its_emulate_setup,
MARKER(__KVM_HOST_SMCCC_FUNC_MAX)
};
diff --git a/arch/arm64/include/asm/kvm_pkvm.h b/arch/arm64/include/asm/kvm_pkvm.h
index 78597210a53c..cc89e2bde468 100644
--- a/arch/arm64/include/asm/kvm_pkvm.h
+++ b/arch/arm64/include/asm/kvm_pkvm.h
@@ -32,8 +32,8 @@ struct pkvm_protected_reg {
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(its_emulate_forward_req)(struct pkvm_protected_reg *region, u64 offset,
- bool write, u64 *reg, u8 reg_size);
+extern void kvm_nvhe_sym(pkvm_its_emulate_handler)(struct pkvm_protected_reg *region, u64 offset,
+ bool write, u64 *reg, u8 reg_size);
int pkvm_init_host_vm(struct kvm *kvm, unsigned long type);
int pkvm_create_hyp_vm(struct kvm *kvm);
diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
index d3df96ed8ba4..ad57b2076eee 100644
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@ -16,6 +16,7 @@
#include <asm/kvm_mmu.h>
#include <nvhe/ffa.h>
+#include <nvhe/its_emulate.h>
#include <nvhe/mem_protect.h>
#include <nvhe/mm.h>
#include <nvhe/pkvm.h>
@@ -705,6 +706,20 @@ static void handle___vgic_v5_restore_vmcr_apr(struct kvm_cpu_context *host_ctxt)
__vgic_v5_restore_vmcr_apr(kern_hyp_va(cpu_if));
}
+static void handle___pkvm_its_emulate_setup(struct kvm_cpu_context *host_ctxt)
+{
+ DECLARE_REG(phys_addr_t, dev_addr, host_ctxt, 1);
+ DECLARE_REG(struct its_host_state *, host_state, host_ctxt, 2);
+ DECLARE_REG(void *, priv_state, host_ctxt, 3);
+ DECLARE_REG(size_t, priv_state_num_pages, host_ctxt, 4);
+
+ if (!is_protected_kvm_enabled())
+ return;
+
+ cpu_reg(host_ctxt, 1) = pkvm_its_emulate_setup(dev_addr, host_state, priv_state,
+ priv_state_num_pages);
+}
+
typedef void (*hcall_t)(struct kvm_cpu_context *);
#define HANDLE_FUNC(x) [__KVM_HOST_SMCCC_FUNC_##x] = (hcall_t)handle_##x
@@ -762,6 +777,7 @@ static const hcall_t host_hcall[] = {
HANDLE_FUNC(__pkvm_vcpu_load),
HANDLE_FUNC(__pkvm_vcpu_put),
HANDLE_FUNC(__pkvm_tlb_flush_vmid),
+ HANDLE_FUNC(__pkvm_its_emulate_setup),
};
static void handle_host_hcall(struct kvm_cpu_context *host_ctxt)
diff --git a/arch/arm64/kvm/hyp/nvhe/its_emulate.c b/arch/arm64/kvm/hyp/nvhe/its_emulate.c
index 82dc60dcde68..8c8acaee4d2b 100644
--- a/arch/arm64/kvm/hyp/nvhe/its_emulate.c
+++ b/arch/arm64/kvm/hyp/nvhe/its_emulate.c
@@ -6,8 +6,8 @@
#include <linux/irqchip/arm-gic-v3.h>
-void its_emulate_forward_req(struct pkvm_protected_reg *region, u64 offset, bool write, u64 *reg,
- u8 reg_size)
+static void its_emulate_forward_req(struct pkvm_protected_reg *region, u64 offset, bool write,
+ u64 *reg, u8 reg_size)
{
void __iomem *addr = __hyp_va(PFN_PHYS(region->pfn) + offset);
diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c
index 4bfffbedac4c..a9ceb9ffe6a4 100644
--- a/arch/arm64/kvm/pkvm.c
+++ b/arch/arm64/kvm/pkvm.c
@@ -71,7 +71,7 @@ static int __init register_its_emulated_region(void)
*/
kvm_nvhe_sym(pkvm_protected_regs)[i].pfn = PHYS_PFN(res.start);
kvm_nvhe_sym(pkvm_protected_regs)[i].cb =
- lm_alias(&kvm_nvhe_sym(its_emulate_forward_req));
+ lm_alias(&kvm_nvhe_sym(pkvm_its_emulate_handler));
kvm_nvhe_sym(pkvm_protected_regs)[i].nr_pages =
PFN_DOWN(min_t(u64, resource_size(&res), PAGE_ALIGN_DOWN(GITS_TRANSLATER)));
@@ -312,8 +312,28 @@ static void __init _kvm_host_prot_finalize(void *arg)
WRITE_ONCE(*err, -EINVAL);
}
+#define ITS_PAGES (2UL)
+
+static int pkvm_init_its_emulation(phys_addr_t dev_addr, struct its_host_state *host)
+{
+ size_t priv_state_sz = ITS_PAGES << PAGE_SHIFT;
+ void *priv_state;
+ int ret;
+
+ priv_state = alloc_pages_exact(priv_state_sz, GFP_ATOMIC);
+ if (!priv_state)
+ return -ENOMEM;
+
+ ret = kvm_call_hyp_nvhe(__pkvm_its_emulate_setup, dev_addr, host, priv_state, ITS_PAGES);
+ if (ret)
+ free_pages_exact(priv_state, priv_state_sz);
+
+ return ret;
+}
+
static int __init pkvm_drop_host_privileges(void)
{
+ unsigned long its_flags;
int ret = 0;
/*
@@ -321,8 +341,10 @@ static int __init pkvm_drop_host_privileges(void)
* once the host stage 2 is installed.
*/
static_branch_enable(&kvm_protected_mode_initialized);
+
+ its_emulate_acquire_locks(&its_flags);
on_each_cpu(_kvm_host_prot_finalize, &ret, 1);
- return ret;
+ return its_emulate_release_locks(ret, &its_flags, pkvm_init_its_emulation);
}
static int __init finalize_pkvm(void)
--
2.55.0.654.g21b8a5bc05-goog
prev parent reply other threads:[~2026-08-07 16:44 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-07 16:43 [PATCH v2 00/13] KVM: ITS hardening for pKVM Sebastian Ene
2026-08-07 16:43 ` [PATCH v2 01/13] KVM: arm64: Donate MMIO to the hypervisor Sebastian Ene
2026-08-07 16:43 ` [PATCH v2 02/13] KVM: arm64: Track host-unmapped MMIO regions in a static array Sebastian Ene
2026-08-07 16:43 ` [PATCH v2 03/13] KVM: arm64: Support host MMIO trap handlers for unmapped devices Sebastian Ene
2026-08-07 16:43 ` [PATCH v2 04/13] KVM: Parse the device tree and register the ITS region with pKVM Sebastian Ene
2026-08-07 16:43 ` [PATCH v2 05/13] irqchip/gic-v3-its: Add support for the ITS emulation setup Sebastian Ene
2026-08-07 16:43 ` [PATCH v2 06/13] KVM: arm64: Shadow the ITS command queue and setup emulation Sebastian Ene
2026-08-07 16:43 ` [PATCH v2 07/13] KVM: arm64: Restrict host access to the private ITS tables Sebastian Ene
2026-08-07 16:43 ` [PATCH v2 08/13] KVM: arm64: Trap & emulate the ITS MAPD command Sebastian Ene
2026-08-07 16:43 ` [PATCH v2 09/13] KVM: arm64: Trap & emulate the ITS MAPC command Sebastian Ene
2026-08-07 16:43 ` [PATCH v2 10/13] KVM: arm64: Restrict host updates to GITS_CTLR Sebastian Ene
2026-08-07 16:43 ` [PATCH v2 11/13] KVM: arm64: Prevent the host from specifying a different command queue Sebastian Ene
2026-08-07 16:43 ` [PATCH v2 12/13] KVM: arm64: Prevent the host from programming new GITS_BASER tables Sebastian Ene
2026-08-07 16:43 ` Sebastian Ene [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260807164322.2970811-15-sebastianene@google.com \
--to=sebastianene@google.com \
--cc=Sascha.Bischoff@arm.com \
--cc=android-kvm@google.com \
--cc=bgrzesik@google.com \
--cc=catalin.marinas@arm.com \
--cc=fuad.tabba@linux.dev \
--cc=joey.gouly@arm.com \
--cc=kvmarm@lists.linux.dev \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=maz@kernel.org \
--cc=nathan@kernel.org \
--cc=oupton@kernel.org \
--cc=perlarsen@google.com \
--cc=rananta@google.com \
--cc=seiden@linux.ibm.com \
--cc=smostafa@google.com \
--cc=suzuki.poulose@arm.com \
--cc=tglx@kernel.org \
--cc=vdonnefort@google.com \
--cc=vladimir.murzin@arm.com \
--cc=will@kernel.org \
--cc=yuzenghui@huawei.com \
--cc=zenghui.yu@linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox