From nobody Thu Apr 9 07:15:58 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