From a63554bccf72ec64dfe49663daefb08bf6b3e597 Mon Sep 17 00:00:00 2001 From: Thomas Glanzmann Date: Thu, 12 Nov 2026 22:23:37 +0100 Subject: [PATCH 1/3] arm64: errata: treat the T8142 vGIC SEIS as broken, like T6040 and T8140 ICH_VTR_EL2 on the J813 (MacBook Air M5, T8142, macOS 27.2 stub) reads 0x90580007 at EL2 on all ten CPUs, E (part 0x062) and P (0x063) cores alike: eight list registers and SEIS set, the value of the other Apple cores in apple_broken_seis_cpus. Add the two T8142 parts so that KVM does not trust the locally generated SError the vGIC claims to support, as for those cores. With it the kernel reports "Known broken GICv3 SEIS implementation" and KVM guests with 4 and 10 vCPUs boot on the J813. Signed-off-by: Thomas Glanzmann --- arch/arm64/kernel/cpu_errata.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index f8116630c743b..9d7e134419fbd 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c @@ -316,6 +316,8 @@ static const struct midr_range apple_broken_seis_cpus[] = { MIDR_ALL_VERSIONS(MIDR_APPLE_T6040_P), MIDR_ALL_VERSIONS(MIDR_APPLE_TAHITI_E), MIDR_ALL_VERSIONS(MIDR_APPLE_TAHITI_P), + MIDR_ALL_VERSIONS(MIDR_APPLE_T8142_E), + MIDR_ALL_VERSIONS(MIDR_APPLE_T8142_P), {}, }; From d224f77bc119d0a7866043b0ad5015f0c85eb389 Mon Sep 17 00:00:00 2001 From: Thomas Glanzmann Date: Thu, 12 Nov 2026 22:37:21 +0100 Subject: [PATCH 2/3] KVM: arm64: Fix up ID_AA64PFR1_EL1.MTE_frac only for a VM with MTE On a host whose sanitised ID_AA64PFR1_EL1 has MTE == MTE2 and MTE_frac == NI (0xf), the M5 MacBook Air (T8142) for one, every VMM that writes the ID registers back after vCPU init fails. QEMU 11.1 reports "Could not set register ... op0:3 op1:0 crn:0 crm:4 op2:1 to 1 (is 1)", whatever -cpu it is given. A VM without MTE sees MTE and MTE_frac as 0: sanitise_id_aa64pfr1_el1() hides both. Writing that value back, set_id_aa64pfr1_el1() takes the MTE_frac of 0 for MTE_ASYNC and replaces it with the host's NI. The result no longer matches the limit, which has MTE_frac cleared, so arm64_check_features() rejects the value KVM itself provided. The fix-up exists so that a VM that has MTE can be given back the value older kernels reported. Apply it only to such a VM. On the J813 at EL2 (sanitised PFR1 0x00000f0002000201): before, KVM refused KVM_SET_ONE_REG of the ID_AA64PFR1_EL1 value it had just returned (0x1); after, QEMU starts KVM guests. Signed-off-by: Thomas Glanzmann --- arch/arm64/kvm/sys_regs.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index f51c3d756b3d8..df4d4a3b479b0 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -2535,9 +2535,14 @@ static int set_id_aa64pfr1_el1(struct kvm_vcpu *vcpu, * ID_AA64PFR1_EL1.MTE_frac to 0. However, ignore it to avoid * incorrectly claiming hardware support for MTE_ASYNC in the * guest. + * + * Only a VM with MTE sees MTE_frac. Without MTE both fields read + * as 0 and the 0 written back must stay 0, or the value no longer + * matches the one KVM itself provided. */ - if (mte == ID_AA64PFR1_EL1_MTE_MTE2 && + if (kvm_has_mte(vcpu->kvm) && + mte == ID_AA64PFR1_EL1_MTE_MTE2 && hw_mte_frac == ID_AA64PFR1_EL1_MTE_frac_NI && user_mte_frac == ID_AA64PFR1_EL1_MTE_frac_ASYNC) { user_val &= ~ID_AA64PFR1_EL1_MTE_frac_MASK; From 14beccbe8824a7ea5ceeeb6e227108dd3a0daf8f Mon Sep 17 00:00:00 2001 From: Thomas Glanzmann Date: Thu, 12 Nov 2026 22:54:14 +0100 Subject: [PATCH 3/3] irqchip/apple-aic: Mask T8142 guest timers through VM_TMR_FIQ_ENA_EL2 at EL2 without SPTM T8142 has vm_timer_fiq_readonly: under the SPTM boot of the first J813 bring-up, writes to VM_TMR_FIQ_ENA_EL2 trapped, so the guest timer FIQs are masked by setting IMASK in CNTP_CTL_EL02 and CNTV_CTL_EL02. Those are the guest's own timer controls. When KVM masks the guest timer FIQ around a vCPU load or after the timer fires, the guest's CNTV_CTL keeps IMASK, KVM saves it as guest state, and the guest gets no timer interrupt again. On the J813 at EL2 every KVM guest stalls the first time it waits for a timer: UEFI right after its banner, Linux in its initramfs. aura runs the OS at EL2 in a CTXR execute window without SPTM, and says so with /chosen/aurora,ctxr-exec-window. There VM_TMR_FIQ_ENA_EL2 takes writes: it reads 0xf and a write back succeeds on all ten J813 CPUs. Use the register in that case and keep the EL02 masking for the others. With it, guests boot to a login prompt on the J813 under 27.2: UEFI with 4 vCPUs (libvirt) in about 18 s and 10 vCPUs in about 16 s; the guest vtimer FIQ is delivered (thousands per CPU, where it had stayed at 2). Signed-off-by: Thomas Glanzmann --- drivers/irqchip/irq-apple-aic.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/irqchip/irq-apple-aic.c b/drivers/irqchip/irq-apple-aic.c index 393596ff6231b..21a43bd7737e5 100644 --- a/drivers/irqchip/irq-apple-aic.c +++ b/drivers/irqchip/irq-apple-aic.c @@ -1286,6 +1286,18 @@ static int __init aic_of_ic_init(struct device_node *node, struct device_node *p irqc->info = *(struct aic_info *)match->data; + /* + * The VM_TMR_FIQ_ENA_EL2 write that traps on T8142 was seen under + * SPTM. A loader that runs the OS at EL2 in a CTXR execute window + * starts no SPTM and says so with this property, and there the + * register takes writes. Masking through the EL02 controls instead + * sets IMASK in the guest's own timer, which KVM then keeps as + * guest state: the guest gets no timer interrupt again. + */ + if (irqc->info.vm_timer_fiq_readonly && is_kernel_in_hyp_mode() && + of_property_present(of_chosen, "aurora,ctxr-exec-window")) + irqc->info.vm_timer_fiq_readonly = false; + aic_irqc = irqc; switch (irqc->info.version) {