From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id E0FA4C43458 for ; Mon, 29 Jun 2026 11:19:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc: To:From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=916EU2qHxciRKmDja1d3pRoDwe+DcI7RyznnJ0SWokA=; b=bCikf2KWkJvDWpJixqDwtDBVcP njq1suo1WAEJu51fCKIcC3ZO/ZbvUsZXBAaQzexk1apnkDhjYh1mUcS4S1DOjeoiaLeUhml6oO1rJ zwvEnM3wNeaVcEgQqQxZuhG2HilWyxshoxdCAfdZ3v+ouIPNPhZlWQtqydVSM6FUcNVg0EHSrGvxs phT7fAXm2PNX03qDnoUjz9KPQ0DwVnELnOY4w/URDjbCFm/JFAgp4xHdtr3wUqISGO5wwa6eOdpuJ +pWiDsAtU9gNKGAEeyYErvFbEHQvG6T6Z0G4H53kVBC/zbY/JQa+bze6Kd104YFFwCpBCSLbacJ9j EWLOysyA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.99.1 #2 (Red Hat Linux)) id 1weA0w-0000000EPgq-2R3E; Mon, 29 Jun 2026 11:18:58 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.99.1 #2 (Red Hat Linux)) id 1weA0s-0000000EPfB-3CaF for linux-arm-kernel@lists.infradead.org; Mon, 29 Jun 2026 11:18:56 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 561942A31; Mon, 29 Jun 2026 04:18:49 -0700 (PDT) Received: from LeoBrasDK.cambridge.arm.com (LeoBrasDK.cambridge.arm.com [10.2.212.21]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 94CD13F905; Mon, 29 Jun 2026 04:18:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1782731933; bh=hZhhpdSNOFRJJHeeJGDabDdoMt2xow3SK8tiRv/XWDs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Ii6C/GP7lLEYsb+IVxIwzWkyOTUyWojcy6Fu7g5AAkCVThFiBV6FrrpZaXmFVHQ75 meYCV8SB2X73ywXKYbDLRUxDD25ceGptDbUWxzQ/R1n5Aoh/2WkqeTUczcjF7LUagi Mn82uJxP3cl3QU/Kf8fxRJhHO04f1zynRcMRGU9M= From: Leonardo Bras To: Catalin Marinas , Will Deacon , Marc Zyngier , Oliver Upton , Joey Gouly , Steffen Eiden , Suzuki K Poulose , Zenghui Yu , "Rafael J. Wysocki" , Len Brown , Saket Dumbre , Paolo Bonzini , Jonathan Cameron , Chengwen Feng , Leonardo Bras , Kees Cook , =?UTF-8?q?Miko=C5=82aj=20Lenczewski?= , James Morse , Zeng Heng , mrigendrachaubey , Thomas Huth , Ryan Roberts , Yeoreum Yun , Mark Brown , Kevin Brodsky , James Clark , Fuad Tabba , Raghavendra Rao Ananta , Lorenzo Pieralisi , Sascha Bischoff , Anshuman Khandual , Tian Zheng Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, kvmarm@lists.linux.dev, linux-acpi@vger.kernel.org, acpica-devel@lists.linux.dev, kvm@vger.kernel.org Subject: [PATCH v2 05/13] KVM: arm64: Detect (via ACPI) and initialize HACDBSIRQ Date: Mon, 29 Jun 2026 12:17:53 +0100 Message-ID: <20260629111820.1873540-6-leo.bras@arm.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260629111820.1873540-1-leo.bras@arm.com> References: <20260629111820.1873540-1-leo.bras@arm.com> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=8768; i=leo.bras@arm.com; h=from:subject; bh=hZhhpdSNOFRJJHeeJGDabDdoMt2xow3SK8tiRv/XWDs=; b=owGbwMvMwCX2pizjszvTwvWMp9WSGLKcQhJsGA7cyfVYcDDzTMs9n8Jfv59x9N/b/eDuKxkut z3ak3XFO0pZGMS4GGTFFFlkH81fxfN9SsaRKz8WwMxhZQIZwsDFKQATEcxkZNjodWTuPLbMM1e+ W8qUXdfeY6DR9GBS2yWxXZ89l/wV1uNgZJh/8P3uS9WslzWyJizPF/25yNjVND/kZeonbQeRM79 tpDgB X-Developer-Key: i=leo.bras@arm.com; a=openpgp; fpr=36E6C95AE0F111CC5B6F4D2E688C33F8A0C5B0C5 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.9.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20260629_041854_882891_01543015 X-CRM114-Status: GOOD ( 24.39 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Find via ACPI [1] the Id for HACDBSIRQ, initialize it as a per-cpu IRQ and make sure any cpu able to run virtualization has it active. Introduce a per-cpu structure used by the HACDBSIRQ handler to keep track of entries size and the status of HACDBS. Size is used to detect end of processing in case the number of entries being processed is different of the supported entries size. Status may look easily replaceable by checking HACDBS registers now, but will make the OFF/IDLE detection easier in next patches. Signed-off-by: Leonardo Bras [1] https://github.com/tianocore/edk2/issues/12409 --- arch/arm64/include/asm/acpi.h | 3 + arch/arm64/include/asm/kvm_dirty_bit.h | 18 +++++ include/acpi/actbl2.h | 1 + arch/arm64/kvm/arm.c | 5 ++ arch/arm64/kvm/dirty_bit.c | 97 ++++++++++++++++++++++++++ 5 files changed, 124 insertions(+) diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h index 8a54ca6ba602..883315e9d79d 100644 --- a/arch/arm64/include/asm/acpi.h +++ b/arch/arm64/include/asm/acpi.h @@ -38,20 +38,23 @@ #define BAD_MADT_GICC_ENTRY(entry, end) \ (!(entry) || (entry)->header.length < ACPI_MADT_GICC_MIN_LENGTH || \ (unsigned long)(entry) + (entry)->header.length > (end)) #define ACPI_MADT_GICC_SPE (offsetof(struct acpi_madt_generic_interrupt, \ spe_interrupt) + sizeof(u16)) #define ACPI_MADT_GICC_TRBE (offsetof(struct acpi_madt_generic_interrupt, \ trbe_interrupt) + sizeof(u16)) + +#define ACPI_MADT_GICC_HACDBSIRQ (offsetof(struct acpi_madt_generic_interrupt, \ + hacdbsirq_gsi) + sizeof(u32)) /* * ArmĀ® Functional Fixed Hardware Specification Version 1.2. * Table 2: Arm Architecture context loss flags */ #define CPUIDLE_CORE_CTXT BIT(0) /* Core context Lost */ static inline unsigned int arch_get_idle_state_flags(u32 arch_flags) { if (arch_flags & CPUIDLE_CORE_CTXT) return CPUIDLE_FLAG_TIMER_STOP; diff --git a/arch/arm64/include/asm/kvm_dirty_bit.h b/arch/arm64/include/asm/kvm_dirty_bit.h index dd16438f0651..904e59f95b7e 100644 --- a/arch/arm64/include/asm/kvm_dirty_bit.h +++ b/arch/arm64/include/asm/kvm_dirty_bit.h @@ -2,11 +2,29 @@ /* * Copyright (C) 2026 ARM Ltd. * Author: Leonardo Bras */ #ifndef __ARM64_KVM_DIRTY_BIT_H__ #define __ARM64_KVM_DIRTY_BIT_H__ #include +enum hacdbs_status { + HACDBS_OFF, + HACDBS_IDLE, + HACDBS_RUNNING, + HACDBS_ERROR +}; + +struct hacdbs { + enum hacdbs_status status; + int size; +}; + +DECLARE_PER_CPU(struct hacdbs, hacdbs_pcp); + +void __init kvm_hacdbs_init(void); +void kvm_hacdbs_cpu_up(void); +void kvm_hacdbs_cpu_down(void); + #endif /* __ARM64_KVM_DIRTY_BIT_H__ */ diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h index baef525367b5..eaefb494ef59 100644 --- a/include/acpi/actbl2.h +++ b/include/acpi/actbl2.h @@ -1442,20 +1442,21 @@ struct acpi_madt_generic_interrupt { u64 gich_base_address; u32 vgic_interrupt; u64 gicr_base_address; u64 arm_mpidr; u8 efficiency_class; u8 reserved2[1]; u16 spe_interrupt; /* ACPI 6.3 */ u16 trbe_interrupt; /* ACPI 6.5 */ u16 iaffid; /* ACPI 6.7 */ u32 irs_id; + u32 hacdbsirq_gsi; /* ACPI 6.X */ }; /* Masks for Flags field above */ /* ACPI_MADT_ENABLED (1) Processor is usable if set */ #define ACPI_MADT_PERFORMANCE_IRQ_MODE (1<<1) /* 01: Performance Interrupt Mode */ #define ACPI_MADT_VGIC_IRQ_MODE (1<<2) /* 02: VGIC Maintenance Interrupt mode */ #define ACPI_MADT_GICC_ONLINE_CAPABLE (1<<3) /* 03: Processor is online capable */ #define ACPI_MADT_GICC_NON_COHERENT (1<<4) /* 04: GIC redistributor is not coherent */ diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index 50adfff75be8..dc1a4629aaeb 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -35,20 +35,21 @@ #include #include #include #include #include #include #include #include #include #include +#include #include #include #include #include #include #include #include @@ -2300,28 +2301,30 @@ int kvm_arch_enable_virtualization_cpu(void) * disabled, but not with preemption disabled. The former is * enough to ensure correctness, but most of the helpers * expect the later and will throw a tantrum otherwise. */ preempt_disable(); cpu_hyp_init(NULL); kvm_vgic_cpu_up(); kvm_timer_cpu_up(); + kvm_hacdbs_cpu_up(); preempt_enable(); return 0; } void kvm_arch_disable_virtualization_cpu(void) { + kvm_hacdbs_cpu_down(); kvm_timer_cpu_down(); kvm_vgic_cpu_down(); if (!is_protected_kvm_enabled()) cpu_hyp_uninit(NULL); } #ifdef CONFIG_CPU_PM static int hyp_init_cpu_pm_notifier(struct notifier_block *self, unsigned long cmd, @@ -2474,20 +2477,22 @@ static int __init init_subsystems(void) goto out; } /* * Init HYP architected timer support */ err = kvm_timer_hyp_init(vgic_present); if (err) goto out; + kvm_hacdbs_init(); + kvm_register_perf_callbacks(); err = kvm_hyp_trace_init(); if (err) kvm_err("Failed to initialize Hyp tracing\n"); out: if (err) hyp_cpu_pm_exit(); diff --git a/arch/arm64/kvm/dirty_bit.c b/arch/arm64/kvm/dirty_bit.c index 32fe938d6bf7..789da8712b1b 100644 --- a/arch/arm64/kvm/dirty_bit.c +++ b/arch/arm64/kvm/dirty_bit.c @@ -1,16 +1,113 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2026 ARM Ltd. * Author: Leonardo Bras */ #include +#include +#include + +DEFINE_PER_CPU(struct hacdbs, hacdbs_pcp) = { + .status = HACDBS_OFF, + .size = 0, +}; /* HDBSS entry field definitions */ #define HDBSS_ENTRY_VALID BIT(0) #define HDBSS_ENTRY_TTWL_SHIFT (1) #define HDBSS_ENTRY_TTWL_MASK (GENMASK(3, 1)) #define HDBSS_ENTRY_TTWL(x) \ (((x) << HDBSS_ENTRY_TTWL_SHIFT) & HDBSS_ENTRY_TTWL_MASK) #define HDBSS_ENTRY_TTWL_RESV HDBSS_ENTRY_TTWL(-4) #define HDBSS_ENTRY_IPA GENMASK_ULL(55, 12) + +static __ro_after_init int hacdbsirq = -1; + +static irqreturn_t hacdbsirq_handler(int irq, void *pcpu) +{ + u64 cons = read_sysreg_s(SYS_HACDBSCONS_EL2); + unsigned long err = FIELD_GET(HACDBSCONS_EL2_ERR_REASON, cons); + + switch (err) { + case HACDBSCONS_EL2_ERR_REASON_NOF: + this_cpu_write(hacdbs_pcp.status, HACDBS_IDLE); + break; + case HACDBSCONS_EL2_ERR_REASON_IPAHACF: + /* When size not a power of two >= 4k, exit with reserved TTLW */ + int index = FIELD_GET(HACDBSCONS_EL2_INDEX, cons); + + if (index >= this_cpu_read(hacdbs_pcp.size)) { + this_cpu_write(hacdbs_pcp.status, HACDBS_IDLE); + break; + } + fallthrough; + case HACDBSCONS_EL2_ERR_REASON_STRUCTF: + case HACDBSCONS_EL2_ERR_REASON_IPAF: + this_cpu_write(hacdbs_pcp.status, HACDBS_ERROR); + break; + } + + return IRQ_HANDLED; +} + +void kvm_hacdbs_cpu_up(void) +{ + if (hacdbsirq < 0) + return; + + enable_percpu_irq(hacdbsirq, IRQ_TYPE_LEVEL_HIGH); + this_cpu_write(hacdbs_pcp.status, HACDBS_IDLE); +} + +void kvm_hacdbs_cpu_down(void) +{ + if (hacdbsirq < 0) + return; + + disable_percpu_irq(hacdbsirq); + this_cpu_write(hacdbs_pcp.status, HACDBS_OFF); +} + +#ifdef CONFIG_ACPI +static int __init hacdbs_acpi_get_irq(void) +{ + struct acpi_madt_generic_interrupt *gicc; + u32 gsi; + int irq; + + gicc = acpi_cpu_get_madt_gicc(smp_processor_id()); + if (gicc->header.length < ACPI_MADT_GICC_HACDBSIRQ) + return -ENXIO; + + gsi = gicc->hacdbsirq_gsi; + + irq = acpi_register_gsi(NULL, gsi, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_HIGH); + if (irq < 0) { + pr_warn("ACPI: Unable to register HACDBS interrupt: %d\n", gsi); + return -ENXIO; + } + + return irq; +} +#else +#define hacdbs_acpi_get_irq() (-ENXIO) +#endif + +void __init kvm_hacdbs_init(void) +{ + int irq; + + /* FEAT_HACDBS is only supported if Linux runs in EL2 (VHE) */ + if (!system_supports_hacdbs() || !is_kernel_in_hyp_mode()) + return; + + irq = hacdbs_acpi_get_irq(); + if (irq < 0) + return; + + if (request_percpu_irq(irq, hacdbsirq_handler, "HACDBSIRQ", &hacdbs_pcp) < 0) + return; + + hacdbsirq = irq; +} -- 2.54.0