* Re: [PATCH v14 20/44] arm64: RMI: Support for the VGIC in realms
From: Steven Price @ 2026-06-05 15:02 UTC (permalink / raw)
To: Gavin Shan, kvm, kvmarm
Cc: Catalin Marinas, Marc Zyngier, Will Deacon, James Morse,
Oliver Upton, Suzuki K Poulose, Zenghui Yu, linux-arm-kernel,
linux-kernel, Joey Gouly, Alexandru Elisei, Christoffer Dall,
Fuad Tabba, linux-coco, Ganapatrao Kulkarni, Shanker Donthineni,
Alper Gun, Aneesh Kumar K . V, Emi Kisanuki, Vishal Annapurve,
WeiLin.Chang, Lorenzo.Pieralisi2
In-Reply-To: <5ea74b6a-a51a-415e-b53f-5ece9829dee8@redhat.com>
On 28/05/2026 05:07, Gavin Shan wrote:
> Hi Steve,
>
> On 5/13/26 11:17 PM, Steven Price wrote:
>> The RMM provides emulation of a VGIC to the realm guest. With RMM v2.0
>> the registers are passed in the system registers so this works similar
>> to a normal guest, but kvm_arch_vcpu_put() need reordering to early out,
>> and realm guests don't support GICv2 even if the host does.
>>
>> Signed-off-by: Steven Price <steven.price@arm.com>
>> ---
>> Changes from v12:
>> * GIC registers are now passed in the system registers rather than via
>> rec_entry/rec_exit which removes most of the changes.
>> Changes from v11:
>> * Minor changes to align with the previous patches. Note that the VGIC
>> handling will change with RMM v2.0.
>> Changes from v10:
>> * Make sure we sync the VGIC v4 state, and only populate valid lrs from
>> the list.
>> Changes from v9:
>> * Copy gicv3_vmcr from the RMM at the same time as gicv3_hcr rather
>> than having to handle that as a special case.
>> Changes from v8:
>> * Propagate gicv3_hcr to from the RMM.
>> Changes from v5:
>> * Handle RMM providing fewer GIC LRs than the hardware supports.
>> ---
>> arch/arm64/kvm/arm.c | 11 ++++++++---
>> arch/arm64/kvm/vgic/vgic-init.c | 2 +-
>> 2 files changed, 9 insertions(+), 4 deletions(-)
>>
>> diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
>> index 93d34762db91..21d9dfdb1ea0 100644
>> --- a/arch/arm64/kvm/arm.c
>> +++ b/arch/arm64/kvm/arm.c
>> @@ -786,19 +786,24 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
>> kvm_call_hyp_nvhe(__pkvm_vcpu_put);
>> }
>> + kvm_timer_vcpu_put(vcpu);
>> + kvm_vgic_put(vcpu);
>> +
>> + vcpu->cpu = -1;
>> +
>> + if (vcpu_is_rec(vcpu))
>> + return;
>> +
>
> For a REC, kvm_vcpu_{load, put}_debug() becomes unbalanced in
> kvm_arch_vcpu_{load, put}().
> kvm_vcpu_load_debug() is called in kvm_arch_vcpu_load(), but
> kvm_vcpu_put_debug() won't
> be called in kvm_arch_vcpu_put() after this whole series is applied.
Good catch. Yes that's not quite right.
Thanks,
Steve
>> kvm_vcpu_put_debug(vcpu);
>> kvm_arch_vcpu_put_fp(vcpu);
>> if (has_vhe())
>> kvm_vcpu_put_vhe(vcpu);
>> - kvm_timer_vcpu_put(vcpu);
>> - kvm_vgic_put(vcpu);
>> kvm_vcpu_pmu_restore_host(vcpu);
>> if (vcpu_has_nv(vcpu))
>> kvm_vcpu_put_hw_mmu(vcpu);
>> kvm_arm_vmid_clear_active();
>> vcpu_clear_on_unsupported_cpu(vcpu);
>> - vcpu->cpu = -1;
>> }
>> static void __kvm_arm_vcpu_power_off(struct kvm_vcpu *vcpu)
>> diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/
>> vgic-init.c
>> index 933983bb2005..a9db963dfd23 100644
>> --- a/arch/arm64/kvm/vgic/vgic-init.c
>> +++ b/arch/arm64/kvm/vgic/vgic-init.c
>> @@ -81,7 +81,7 @@ int kvm_vgic_create(struct kvm *kvm, u32 type)
>> * the proper checks already.
>> */
>> if (type == KVM_DEV_TYPE_ARM_VGIC_V2 &&
>> - !kvm_vgic_global_state.can_emulate_gicv2)
>> + (!kvm_vgic_global_state.can_emulate_gicv2 || kvm_is_realm(kvm)))
>> return -ENODEV;
>> /*
>
> Thanks,
> Gavin
>
^ permalink raw reply
* Re: [PATCH v14 19/44] arm64: RMI: Allocate/free RECs to match vCPUs
From: Steven Price @ 2026-06-05 15:02 UTC (permalink / raw)
To: Wei-Lin Chang, kvm, kvmarm
Cc: Catalin Marinas, Marc Zyngier, Will Deacon, James Morse,
Oliver Upton, Suzuki K Poulose, Zenghui Yu, linux-arm-kernel,
linux-kernel, Joey Gouly, Alexandru Elisei, Christoffer Dall,
Fuad Tabba, linux-coco, Ganapatrao Kulkarni, Gavin Shan,
Shanker Donthineni, Alper Gun, Aneesh Kumar K . V, Emi Kisanuki,
Vishal Annapurve, Lorenzo.Pieralisi2
In-Reply-To: <2uvtjhncf57yek5i4fupdefunukmidzw452mcavnmixpr5u3qd@uoaktzpak3nl>
On 26/05/2026 23:39, Wei-Lin Chang wrote:
> Hi,
>
> On Wed, May 13, 2026 at 02:17:27PM +0100, Steven Price wrote:
>> The RMM maintains a data structure known as the Realm Execution Context
>> (or REC). It is similar to struct kvm_vcpu and tracks the state of the
>> virtual CPUs. KVM must delegate memory and request the structures are
>> created when vCPUs are created, and suitably tear down on destruction.
>>
>> RECs may require additional pages (e.g. for storing larger register
>> state for SVE). The RMM can request extra pages for this purpose using
>> the Stateful RMI Operations (SRO) functionality to request pages during
>> REC creation. These pages are then passed back to the host from the RMM
>> ('reclaimed') when the REC is destroyed. The kernel tracking object
>> (struct rmi_sro_state) is stored in the realm_rec structure to avoid
>> memory allocation during the destruction path.
>>
>> Note that only some of register state for the REC can be set by KVM, the
>> rest is defined by the RMM (zeroed). The register state then cannot be
>> changed by KVM after the REC is created (except when the guest
>> explicitly requests this e.g. by performing a PSCI call).
>>
>> Signed-off-by: Steven Price <steven.price@arm.com>
>> ---
>> Changes since v13:
>> * Support SRO for REC creation/destruction instead of auxiliary
>> granules.
>> Changes since v12:
>> * Use the new range-based delegation RMI.
>> Changes since v11:
>> * Remove the KVM_ARM_VCPU_REC feature. User space no longer needs to
>> configure each VCPU separately, RECs are created on the first VCPU
>> run of the guest.
>> Changes since v9:
>> * Size the aux_pages array according to the PAGE_SIZE of the host.
>> Changes since v7:
>> * Add comment explaining the aux_pages array.
>> * Rename "undeleted_failed" variable to "should_free" to avoid a
>> confusing double negative.
>> Changes since v6:
>> * Avoid reporting the KVM_ARM_VCPU_REC feature if the guest isn't a
>> realm guest.
>> * Support host page size being larger than RMM's granule size when
>> allocating/freeing aux granules.
>> Changes since v5:
>> * Separate the concept of vcpu_is_rec() and
>> kvm_arm_vcpu_rec_finalized() by using the KVM_ARM_VCPU_REC feature as
>> the indication that the VCPU is a REC.
>> Changes since v2:
>> * Free rec->run earlier in kvm_destroy_realm() and adapt to previous patches.
>> ---
>> arch/arm64/include/asm/kvm_emulate.h | 2 +-
>> arch/arm64/include/asm/kvm_host.h | 3 +
>> arch/arm64/include/asm/kvm_rmi.h | 17 +++++
>> arch/arm64/kvm/arm.c | 6 ++
>> arch/arm64/kvm/reset.c | 1 +
>> arch/arm64/kvm/rmi.c | 105 +++++++++++++++++++++++++++
>> 6 files changed, 133 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
>> index 82fd777bd9bb..2e69fe494716 100644
>> --- a/arch/arm64/include/asm/kvm_emulate.h
>> +++ b/arch/arm64/include/asm/kvm_emulate.h
>> @@ -714,7 +714,7 @@ static inline bool kvm_realm_is_created(struct kvm *kvm)
>>
>> static inline bool vcpu_is_rec(const struct kvm_vcpu *vcpu)
>> {
>> - return false;
>> + return kvm_is_realm(vcpu->kvm);
>> }
>>
>> #endif /* __ARM64_KVM_EMULATE_H__ */
>> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
>> index 3512696ed506..39b5de03d0fe 100644
>> --- a/arch/arm64/include/asm/kvm_host.h
>> +++ b/arch/arm64/include/asm/kvm_host.h
>> @@ -969,6 +969,9 @@ struct kvm_vcpu_arch {
>>
>> /* Hyp-readable copy of kvm_vcpu::pid */
>> pid_t pid;
>> +
>> + /* Realm meta data */
>> + struct realm_rec rec;
>> };
>>
>> /*
>> diff --git a/arch/arm64/include/asm/kvm_rmi.h b/arch/arm64/include/asm/kvm_rmi.h
>> index 8bd743093ccf..d99bf4fc3c39 100644
>> --- a/arch/arm64/include/asm/kvm_rmi.h
>> +++ b/arch/arm64/include/asm/kvm_rmi.h
>> @@ -59,6 +59,22 @@ struct realm {
>> unsigned int ia_bits;
>> };
>>
>> +/**
>> + * struct realm_rec - Additional per VCPU data for a Realm
>> + *
>> + * @mpidr: MPIDR (Multiprocessor Affinity Register) value to identify this VCPU
>> + * @rec_page: Kernel VA of the RMM's private page for this REC
>> + * @aux_pages: Additional pages private to the RMM for this REC
>> + * @run: Kernel VA of the RmiRecRun structure shared with the RMM
>> + * @sro: A preallocated SRO state context
>> + */
>> +struct realm_rec {
>> + unsigned long mpidr;
>> + void *rec_page;
>> + struct rec_run *run;
>> + struct rmi_sro_state *sro;
>> +};
>> +
>> void kvm_init_rmi(void);
>> u32 kvm_realm_ipa_limit(void);
>>
>> @@ -66,6 +82,7 @@ int kvm_init_realm(struct kvm *kvm);
>> int kvm_activate_realm(struct kvm *kvm);
>> void kvm_destroy_realm(struct kvm *kvm);
>> void kvm_realm_destroy_rtts(struct kvm *kvm);
>> +void kvm_destroy_rec(struct kvm_vcpu *vcpu);
>>
>> static inline bool kvm_realm_is_private_address(struct realm *realm,
>> unsigned long addr)
>> diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
>> index eb2b61fe1f0a..93d34762db91 100644
>> --- a/arch/arm64/kvm/arm.c
>> +++ b/arch/arm64/kvm/arm.c
>> @@ -586,6 +586,8 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
>> /* Force users to call KVM_ARM_VCPU_INIT */
>> vcpu_clear_flag(vcpu, VCPU_INITIALIZED);
>>
>> + vcpu->arch.rec.mpidr = INVALID_HWID;
>> +
>> vcpu->arch.mmu_page_cache.gfp_zero = __GFP_ZERO;
>>
>> /* Set up the timer */
>> @@ -1651,6 +1653,10 @@ static int kvm_vcpu_init_check_features(struct kvm_vcpu *vcpu,
>> if (test_bit(KVM_ARM_VCPU_HAS_EL2, &features))
>> return -EINVAL;
>>
>> + /* Realms are incompatible with AArch32 */
>> + if (vcpu_is_rec(vcpu))
>> + return -EINVAL;
>> +
>> return 0;
>> }
>>
>> diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
>> index b963fd975aac..c18cdca7d125 100644
>> --- a/arch/arm64/kvm/reset.c
>> +++ b/arch/arm64/kvm/reset.c
>> @@ -161,6 +161,7 @@ void kvm_arm_vcpu_destroy(struct kvm_vcpu *vcpu)
>> free_page((unsigned long)vcpu->arch.ctxt.vncr_array);
>> kfree(vcpu->arch.vncr_tlb);
>> kfree(vcpu->arch.ccsidr);
>> + kvm_destroy_rec(vcpu);
>> }
>>
>> static void kvm_vcpu_reset_sve(struct kvm_vcpu *vcpu)
>> diff --git a/arch/arm64/kvm/rmi.c b/arch/arm64/kvm/rmi.c
>> index 849111817af7..353a5ca45e78 100644
>> --- a/arch/arm64/kvm/rmi.c
>> +++ b/arch/arm64/kvm/rmi.c
>> @@ -173,9 +173,108 @@ static int realm_ensure_created(struct kvm *kvm)
>> return -ENXIO;
>> }
>>
>> +static int kvm_create_rec(struct kvm_vcpu *vcpu)
>> +{
>> + struct user_pt_regs *vcpu_regs = vcpu_gp_regs(vcpu);
>> + unsigned long mpidr = kvm_vcpu_get_mpidr_aff(vcpu);
>> + struct realm *realm = &vcpu->kvm->arch.realm;
>> + struct realm_rec *rec = &vcpu->arch.rec;
>> + unsigned long rec_page_phys;
>> + struct rec_params *params;
>> + int r, i;
>> +
>> + if (rec->run)
>> + return -EBUSY;
>> +
>> + /*
>> + * The RMM will report PSCI v1.0 to Realms and the KVM_ARM_VCPU_PSCI_0_2
>> + * flag covers v0.2 and onwards.
>> + */
>> + if (!vcpu_has_feature(vcpu, KVM_ARM_VCPU_PSCI_0_2))
>> + return -EINVAL;
>> +
>> + BUILD_BUG_ON(sizeof(*params) > PAGE_SIZE);
>> + BUILD_BUG_ON(sizeof(*rec->run) > PAGE_SIZE);
>> +
>> + params = (struct rec_params *)get_zeroed_page(GFP_KERNEL);
>> + rec->rec_page = (void *)__get_free_page(GFP_KERNEL);
>> + rec->run = (void *)get_zeroed_page(GFP_KERNEL);
>
> Should this be cast to (struct rec_run *) ?
Yes it probably should - I'll update. Although IMHO get_zeroed_page()
should really return void * - but I know that would be a contentious change.
Thanks,
Steve
>> + rec->sro = kmalloc_obj(*rec->sro);
>> + if (!params || !rec->rec_page || !rec->run || !rec->sro) {
>> + r = -ENOMEM;
>> + goto out_free_pages;
>> + }
>> +
>> + for (i = 0; i < ARRAY_SIZE(params->gprs); i++)
>> + params->gprs[i] = vcpu_regs->regs[i];
>> +
>> + params->pc = vcpu_regs->pc;
>> +
>> + if (vcpu->vcpu_id == 0)
>> + params->flags |= REC_PARAMS_FLAG_RUNNABLE;
>> +
>> + rec_page_phys = virt_to_phys(rec->rec_page);
>> +
>> + if (rmi_delegate_page(rec_page_phys)) {
>> + r = -ENXIO;
>> + goto out_free_pages;
>> + }
>> +
>> + params->mpidr = mpidr;
>> +
>> + if (rmi_rec_create(virt_to_phys(realm->rd), rec_page_phys,
>> + virt_to_phys(params), rec->sro)) {
>> + r = -ENXIO;
>> + goto out_undelegate_rmm_rec;
>> + }
>> +
>> + rec->mpidr = mpidr;
>> +
>> + free_page((unsigned long)params);
>> + return 0;
>> +
>> +out_undelegate_rmm_rec:
>> + if (WARN_ON(rmi_undelegate_page(rec_page_phys)))
>> + rec->rec_page = NULL;
>> +out_free_pages:
>> + free_page((unsigned long)rec->run);
>> + free_page((unsigned long)rec->rec_page);
>> + free_page((unsigned long)params);
>> + kfree(rec->sro);
>> + rec->run = NULL;
>> + return r;
>> +}
>> +
>
> [...]
>
> Thanks,
> Wei-Lin Chang
^ permalink raw reply
* Re: [PATCH v14 17/44] arm64: RMI: RTT tear down
From: Steven Price @ 2026-06-05 15:01 UTC (permalink / raw)
To: Wei-Lin Chang, kvm, kvmarm
Cc: Catalin Marinas, Marc Zyngier, Will Deacon, James Morse,
Oliver Upton, Suzuki K Poulose, Zenghui Yu, linux-arm-kernel,
linux-kernel, Joey Gouly, Alexandru Elisei, Christoffer Dall,
Fuad Tabba, linux-coco, Ganapatrao Kulkarni, Gavin Shan,
Shanker Donthineni, Alper Gun, Aneesh Kumar K . V, Emi Kisanuki,
Vishal Annapurve, Lorenzo.Pieralisi2
In-Reply-To: <mpesc2j3czpunbg3pvgwbotvfn7vahaabvoiu77vd2g5uervho@255lwycekmxh>
On 26/05/2026 23:32, Wei-Lin Chang wrote:
> Hi,
>
> On Wed, May 13, 2026 at 02:17:25PM +0100, Steven Price wrote:
>> The RMM owns the stage 2 page tables for a realm, and KVM must request
>> that the RMM creates/destroys entries as necessary. The physical pages
>> to store the page tables are delegated to the realm as required, and can
>> be undelegated when no longer used.
>>
>> Creating new RTTs is the easy part, tearing down is a little more
>> tricky. The result of realm_rtt_destroy() can be used to effectively
>> walk the tree and destroy the entries (undelegating pages that were
>> given to the realm).
>>
>> Signed-off-by: Steven Price <steven.price@arm.com>
>> ---
>> Changes since v13:
>> * Avoid the double call of kvm_free_stage2_pgd() by splitting the work
>> across that and a new function kvm_realm_uninit_stage2() which is
>> only called for realm guests.
>> Changes since v12:
>> * Simplify some functions now we know RMM page size is the same as the
>> host's.
>> Changes since v11:
>> * Moved some code from earlier in the series to this one so that it's
>> added when it's first used.
>> Changes since v10:
>> * RME->RMI rename.
>> * Some code to handle freeing stage 2 PGD moved into this patch where
>> it belongs.
>> Changes since v9:
>> * Add a comment clarifying that root level RTTs are not destroyed until
>> after the RD is destroyed.
>> Changes since v8:
>> * Introduce free_rtt() wrapper which calls free_delegated_granule()
>> followed by kvm_account_pgtable_pages(). This makes it clear where an
>> RTT is being freed rather than just a delegated granule.
>> Changes since v6:
>> * Move rme_rtt_level_mapsize() and supporting defines from kvm_rme.h
>> into rme.c as they are only used in that file.
>> Changes since v5:
>> * Rename some RME_xxx defines to do with page sizes as RMM_xxx - they are
>> a property of the RMM specification not the RME architecture.
>> Changes since v2:
>> * Moved {alloc,free}_delegated_page() and ensure_spare_page() to a
>> later patch when they are actually used.
>> * Some simplifications now rmi_xxx() functions allow NULL as an output
>> parameter.
>> * Improved comments and code layout.
>> ---
>> arch/arm64/include/asm/kvm_rmi.h | 7 ++
>> arch/arm64/kvm/mmu.c | 21 ++++-
>> arch/arm64/kvm/rmi.c | 148 +++++++++++++++++++++++++++++++
>> 3 files changed, 174 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/kvm_rmi.h b/arch/arm64/include/asm/kvm_rmi.h
>> index 9de34983ee52..06ba0d4745c6 100644
>> --- a/arch/arm64/include/asm/kvm_rmi.h
>> +++ b/arch/arm64/include/asm/kvm_rmi.h
>> @@ -64,5 +64,12 @@ u32 kvm_realm_ipa_limit(void);
>>
>> int kvm_init_realm(struct kvm *kvm);
>> void kvm_destroy_realm(struct kvm *kvm);
>> +void kvm_realm_destroy_rtts(struct kvm *kvm);
>> +
>> +static inline bool kvm_realm_is_private_address(struct realm *realm,
>> + unsigned long addr)
>> +{
>> + return !(addr & BIT(realm->ia_bits - 1));
>> +}
>>
>> #endif /* __ASM_KVM_RMI_H */
>> diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
>> index ba8286472286..eb56d4e7f21a 100644
>> --- a/arch/arm64/kvm/mmu.c
>> +++ b/arch/arm64/kvm/mmu.c
>> @@ -1024,9 +1024,26 @@ int kvm_init_stage2_mmu(struct kvm *kvm, struct kvm_s2_mmu *mmu, unsigned long t
>> return err;
>> }
>>
>> +static void kvm_realm_uninit_stage2(struct kvm_s2_mmu *mmu)
>> +{
>> + struct kvm *kvm = kvm_s2_mmu_to_kvm(mmu);
>> + struct realm *realm = &kvm->arch.realm;
>> +
>> + if (kvm_realm_state(kvm) != REALM_STATE_ACTIVE)
>> + return;
>> +
>> + write_lock(&kvm->mmu_lock);
>> + kvm_stage2_unmap_range(mmu, 0, BIT(realm->ia_bits - 1), true);
>> + write_unlock(&kvm->mmu_lock);
>> + kvm_realm_destroy_rtts(kvm);
>> +}
>> +
>> void kvm_uninit_stage2_mmu(struct kvm *kvm)
>> {
>> - kvm_free_stage2_pgd(&kvm->arch.mmu);
>> + if (kvm_is_realm(kvm))
>> + kvm_realm_uninit_stage2(&kvm->arch.mmu);
>> + else
>> + kvm_free_stage2_pgd(&kvm->arch.mmu);
>> kvm_mmu_free_memory_cache(&kvm->arch.mmu.split_page_cache);
>> }
>>
>> @@ -1103,7 +1120,7 @@ void stage2_unmap_vm(struct kvm *kvm)
>> void kvm_free_stage2_pgd(struct kvm_s2_mmu *mmu)
>> {
>> struct kvm *kvm = kvm_s2_mmu_to_kvm(mmu);
>> - struct kvm_pgtable *pgt = NULL;
>> + struct kvm_pgtable *pgt;
>>
>> write_lock(&kvm->mmu_lock);
>> pgt = mmu->pgt;
>> diff --git a/arch/arm64/kvm/rmi.c b/arch/arm64/kvm/rmi.c
>> index f51ec667445e..5b00ccca4af3 100644
>> --- a/arch/arm64/kvm/rmi.c
>> +++ b/arch/arm64/kvm/rmi.c
>> @@ -11,6 +11,14 @@
>> #include <asm/rmi_cmds.h>
>> #include <asm/virt.h>
>>
>> +static inline unsigned long rmi_rtt_level_mapsize(int level)
>> +{
>> + if (WARN_ON(level > KVM_PGTABLE_LAST_LEVEL))
>> + return PAGE_SIZE;
>> +
>> + return (1UL << ARM64_HW_PGTABLE_LEVEL_SHIFT(level));
>> +}
>> +
>> static bool rmi_has_feature(unsigned long feature)
>> {
>> return !!u64_get_bits(rmm_feat_reg0, feature);
>> @@ -21,6 +29,144 @@ u32 kvm_realm_ipa_limit(void)
>> return u64_get_bits(rmm_feat_reg0, RMI_FEATURE_REGISTER_0_S2SZ);
>> }
>>
>> +static int get_start_level(struct realm *realm)
>> +{
>> + return 4 - stage2_pgtable_levels(realm->ia_bits);
>> +}
>> +
>> +static void free_rtt(phys_addr_t phys)
>> +{
>> + if (free_delegated_page(phys))
>> + return;
>> +
>> + kvm_account_pgtable_pages(phys_to_virt(phys), -1);
>> +}
>> +
>> +/*
>> + * realm_rtt_destroy - Destroy an RTT at @level for @addr.
>> + *
>> + * Returns - Result of the RMI_RTT_DESTROY call, and:
>> + * @rtt_granule: RTT granule, if the RTT was destroyed.
>> + * @next_addr: IPA corresponding to the next possible valid entry we
>> + * can target
>> + */
>> +static int realm_rtt_destroy(struct realm *realm, unsigned long addr,
>> + int level, phys_addr_t *rtt_granule,
>> + unsigned long *next_addr)
>> +{
>> + unsigned long out_rtt;
>> + int ret;
>> +
>> + ret = rmi_rtt_destroy(virt_to_phys(realm->rd), addr, level,
>> + &out_rtt, next_addr);
>> +
>> + *rtt_granule = out_rtt;
>> +
>> + return ret;
>> +}
>
> Looks like out_rtt can be simplified out.
The issue here is there's a type conversion going on. rmi_rtt_destroy()
takes an "unsigned long *" to match the general approach of using
"unsigned long" for the inputs/outputs of SMCCC calls. But rtt_granule
is a "phys_addr_t". While we know these are (currently) the same size,
they are not the same type according to the compiler - phys_addr_t is
"long long unsigned int".
Thanks,
Steve
> [...]
>
> Thanks,
> Wei-Lin Chang
^ permalink raw reply
* Re: [PATCH v14 17/44] arm64: RMI: RTT tear down
From: Steven Price @ 2026-06-05 15:01 UTC (permalink / raw)
To: Wei-Lin Chang, kvm, kvmarm
Cc: Catalin Marinas, Marc Zyngier, Will Deacon, James Morse,
Oliver Upton, Suzuki K Poulose, Zenghui Yu, linux-arm-kernel,
linux-kernel, Joey Gouly, Alexandru Elisei, Christoffer Dall,
Fuad Tabba, linux-coco, Ganapatrao Kulkarni, Gavin Shan,
Shanker Donthineni, Alper Gun, Aneesh Kumar K . V, Emi Kisanuki,
Vishal Annapurve, Lorenzo.Pieralisi2
In-Reply-To: <7egwow26r6sbbtm53mujbhpwyts2utzv2ddth7554kqwbk7k7d@iptjpvvbsc2n>
On 26/05/2026 23:27, Wei-Lin Chang wrote:
> Hi,
>
> On Wed, May 13, 2026 at 02:17:25PM +0100, Steven Price wrote:
>> The RMM owns the stage 2 page tables for a realm, and KVM must request
>> that the RMM creates/destroys entries as necessary. The physical pages
>> to store the page tables are delegated to the realm as required, and can
>> be undelegated when no longer used.
>>
>> Creating new RTTs is the easy part, tearing down is a little more
>> tricky. The result of realm_rtt_destroy() can be used to effectively
>> walk the tree and destroy the entries (undelegating pages that were
>> given to the realm).
>>
>> Signed-off-by: Steven Price <steven.price@arm.com>
>> ---
>> Changes since v13:
>> * Avoid the double call of kvm_free_stage2_pgd() by splitting the work
>> across that and a new function kvm_realm_uninit_stage2() which is
>> only called for realm guests.
>> Changes since v12:
>> * Simplify some functions now we know RMM page size is the same as the
>> host's.
>> Changes since v11:
>> * Moved some code from earlier in the series to this one so that it's
>> added when it's first used.
>> Changes since v10:
>> * RME->RMI rename.
>> * Some code to handle freeing stage 2 PGD moved into this patch where
>> it belongs.
>> Changes since v9:
>> * Add a comment clarifying that root level RTTs are not destroyed until
>> after the RD is destroyed.
>> Changes since v8:
>> * Introduce free_rtt() wrapper which calls free_delegated_granule()
>> followed by kvm_account_pgtable_pages(). This makes it clear where an
>> RTT is being freed rather than just a delegated granule.
>> Changes since v6:
>> * Move rme_rtt_level_mapsize() and supporting defines from kvm_rme.h
>> into rme.c as they are only used in that file.
>> Changes since v5:
>> * Rename some RME_xxx defines to do with page sizes as RMM_xxx - they are
>> a property of the RMM specification not the RME architecture.
>> Changes since v2:
>> * Moved {alloc,free}_delegated_page() and ensure_spare_page() to a
>> later patch when they are actually used.
>> * Some simplifications now rmi_xxx() functions allow NULL as an output
>> parameter.
>> * Improved comments and code layout.
>> ---
>> arch/arm64/include/asm/kvm_rmi.h | 7 ++
>> arch/arm64/kvm/mmu.c | 21 ++++-
>> arch/arm64/kvm/rmi.c | 148 +++++++++++++++++++++++++++++++
>> 3 files changed, 174 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/kvm_rmi.h b/arch/arm64/include/asm/kvm_rmi.h
>> index 9de34983ee52..06ba0d4745c6 100644
>> --- a/arch/arm64/include/asm/kvm_rmi.h
>> +++ b/arch/arm64/include/asm/kvm_rmi.h
>> @@ -64,5 +64,12 @@ u32 kvm_realm_ipa_limit(void);
>>
>> int kvm_init_realm(struct kvm *kvm);
>> void kvm_destroy_realm(struct kvm *kvm);
>> +void kvm_realm_destroy_rtts(struct kvm *kvm);
>> +
>> +static inline bool kvm_realm_is_private_address(struct realm *realm,
>> + unsigned long addr)
>> +{
>> + return !(addr & BIT(realm->ia_bits - 1));
>> +}
>>
>> #endif /* __ASM_KVM_RMI_H */
>> diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
>> index ba8286472286..eb56d4e7f21a 100644
>> --- a/arch/arm64/kvm/mmu.c
>> +++ b/arch/arm64/kvm/mmu.c
>> @@ -1024,9 +1024,26 @@ int kvm_init_stage2_mmu(struct kvm *kvm, struct kvm_s2_mmu *mmu, unsigned long t
>> return err;
>> }
>>
>> +static void kvm_realm_uninit_stage2(struct kvm_s2_mmu *mmu)
>> +{
>> + struct kvm *kvm = kvm_s2_mmu_to_kvm(mmu);
>> + struct realm *realm = &kvm->arch.realm;
>> +
>> + if (kvm_realm_state(kvm) != REALM_STATE_ACTIVE)
>> + return;
>> +
>> + write_lock(&kvm->mmu_lock);
>> + kvm_stage2_unmap_range(mmu, 0, BIT(realm->ia_bits - 1), true);
>> + write_unlock(&kvm->mmu_lock);
>> + kvm_realm_destroy_rtts(kvm);
>> +}
>> +
>> void kvm_uninit_stage2_mmu(struct kvm *kvm)
>> {
>> - kvm_free_stage2_pgd(&kvm->arch.mmu);
>> + if (kvm_is_realm(kvm))
>> + kvm_realm_uninit_stage2(&kvm->arch.mmu);
>> + else
>> + kvm_free_stage2_pgd(&kvm->arch.mmu);
>> kvm_mmu_free_memory_cache(&kvm->arch.mmu.split_page_cache);
>> }
>>
>> @@ -1103,7 +1120,7 @@ void stage2_unmap_vm(struct kvm *kvm)
>> void kvm_free_stage2_pgd(struct kvm_s2_mmu *mmu)
>> {
>> struct kvm *kvm = kvm_s2_mmu_to_kvm(mmu);
>> - struct kvm_pgtable *pgt = NULL;
>> + struct kvm_pgtable *pgt;
>
> Is this included by accident?
Thanks for spotting that. Yes that change shouldn't have sneaked in
here. The original code before this series had the redundant assignment
to NULL. But it's unrelated to this patch so I'll drop the change.
Thanks,
Steve
>
>>
>> write_lock(&kvm->mmu_lock);
>> pgt = mmu->pgt;
>
> [...]
>
> Thanks,
> Wei-Lin Chang
^ permalink raw reply
* Re: [PATCH] net: stmmac: xgmac: report L3/L4 filter match count in ethtool stats
From: Maxime Chevallier @ 2026-06-05 14:55 UTC (permalink / raw)
To: muhammad.nazim.amirul.nazle.asmade, netdev
Cc: andrew+netdev, davem, edumazet, kuba, pabeni, mcoquelin.stm32,
alexandre.torgue, rmk+kernel, linux-stm32, linux-arm-kernel,
linux-kernel
In-Reply-To: <20260604083037.24407-1-muhammad.nazim.amirul.nazle.asmade@altera.com>
Hi,
You're missing the 'net-next' in the Patch subject :(
Besides that,
On 6/4/26 10:30, muhammad.nazim.amirul.nazle.asmade@altera.com wrote:
> From: Nazim Amirul <muhammad.nazim.amirul.nazle.asmade@altera.com>
>
> Read the L3FM and L4FM bits from the RX descriptor status word (RDES2)
> and increment the corresponding ethtool statistics counters. This allows
> users to observe L3/L4 filter hit rates via ethtool -S.
>
> Signed-off-by: Rohan G Thomas <rohan.g.thomas@altera.com>
> Signed-off-by: Nazim Amirul <muhammad.nazim.amirul.nazle.asmade@altera.com>
Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Maxime
> ---
> drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h | 2 ++
> drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c | 6 ++++++
> 2 files changed, 8 insertions(+)
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
> index 51943705a2b0..95fdf3133208 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
> @@ -429,6 +429,8 @@
> #define XGMAC_TDES3_VLTV BIT(16)
> #define XGMAC_TDES3_VT GENMASK(15, 0)
> #define XGMAC_TDES3_FL GENMASK(14, 0)
> +#define XGMAC_RDES2_L4FM BIT(28)
> +#define XGMAC_RDES2_L3FM BIT(27)
> #define XGMAC_RDES2_HL GENMASK(9, 0)
> #define XGMAC_RDES3_OWN BIT(31)
> #define XGMAC_RDES3_CTXT BIT(30)
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c
> index b5f200a87484..6719ac6e395b 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c
> @@ -27,6 +27,7 @@ static int dwxgmac2_get_rx_status(struct stmmac_extra_stats *x,
> struct dma_desc *p)
> {
> u32 rdes3 = le32_to_cpu(p->des3);
> + u32 rdes2 = le32_to_cpu(p->des2);
>
> if (unlikely(rdes3 & XGMAC_RDES3_OWN))
> return dma_own;
> @@ -37,6 +38,11 @@ static int dwxgmac2_get_rx_status(struct stmmac_extra_stats *x,
> if (unlikely((rdes3 & XGMAC_RDES3_ES) && (rdes3 & XGMAC_RDES3_LD)))
> return discard_frame;
>
> + if (rdes2 & XGMAC_RDES2_L3FM)
> + x->l3_filter_match++;
> + if (rdes2 & XGMAC_RDES2_L4FM)
> + x->l4_filter_match++;
> +
> return good_frame;
> }
>
^ permalink raw reply
* Re: [PATCH bpf-next v2 5/8] bpf, x86: emit KASAN checks into x86 JITed programs
From: Yonghong Song @ 2026-06-05 14:54 UTC (permalink / raw)
To: Alexis Lothoré (eBPF Foundation), Alexei Starovoitov,
Daniel Borkmann, Andrii Nakryiko, Martin KaFai Lau,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Song Liu, Jiri Olsa,
John Fastabend, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, x86, H. Peter Anvin, Shuah Khan, Maxime Coquelin,
Alexandre Torgue, Ihor Solodrai
Cc: ebpf, Bastien Curutchet, Thomas Petazzoni, bpf, linux-kernel,
linux-kselftest, linux-stm32, linux-arm-kernel
In-Reply-To: <20260604-kasan-v2-5-c066e627fda8@bootlin.com>
On 6/4/26 1:22 PM, Alexis Lothoré (eBPF Foundation) wrote:
> Insert KASAN shadow memory checks before memory load and store
> operations in JIT-compiled BPF programs. This helps detect memory safety
> bugs such as use-after-free and out-of-bounds accesses at runtime.
>
> The main instructions being targeted are BPF_ST, BPF_STX and BPF_LDX,
> but not all of them are being instrumented:
> - if the load/store instruction is in fact accessing the program stack,
> emit_kasan_check silently skips the instrumentation, as we already
> have page guards to monitor stack accesses.
> - if the load/store instruction is a BPF_PROBE_MEM or a BPF_PROBE_ATOMIC
> instruction, we do not instrument it, as the passed address can fault
> (hence the custom fault management with BPF_PROBE_XXX instructions),
> and so the corresponding kasan check could fault as well.
>
> Signed-off-by: Alexis Lothoré (eBPF Foundation) <alexis.lothore@bootlin.com>
> ---
> Changes in v2:
> - support BPF_ATOMICS
> - support BPF_ST
> - make sure to systematically pass correct instruction to kasan check
> ---
> arch/x86/net/bpf_jit_comp.c | 63 ++++++++++++++++++++++++++++++++++++++-------
> 1 file changed, 53 insertions(+), 10 deletions(-)
>
> diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
> index 943a0f315cf2..cb3c03edc4bd 100644
> --- a/arch/x86/net/bpf_jit_comp.c
> +++ b/arch/x86/net/bpf_jit_comp.c
> @@ -1516,17 +1516,30 @@ static int emit_atomic_rmw_index(u8 **pprog, u32 atomic_op, u32 size,
> return 0;
> }
>
> -static int emit_atomic_ld_st(u8 **pprog, u32 atomic_op, u32 dst_reg,
> - u32 src_reg, s16 off, u8 bpf_size)
> +static int emit_atomic_ld_st(u8 **pprog, struct bpf_insn *insn, u8 *ip,
> + u32 dst_reg, u32 src_reg, bool accesses_stack_only)
> {
> + u32 atomic_op = insn->imm;
> + int err;
> +
> switch (atomic_op) {
> case BPF_LOAD_ACQ:
> + err = emit_kasan_check(pprog, src_reg, insn, ip, false,
> + accesses_stack_only);
> + if (err)
> + return err;
> /* dst_reg = smp_load_acquire(src_reg + off16) */
> - emit_ldx(pprog, bpf_size, dst_reg, src_reg, off);
> + emit_ldx(pprog, BPF_SIZE(insn->code), dst_reg, src_reg,
> + insn->off);
> break;
> case BPF_STORE_REL:
> + err = emit_kasan_check(pprog, dst_reg, insn, ip, true,
> + accesses_stack_only);
> + if (err)
> + return err;
> /* smp_store_release(dst_reg + off16, src_reg) */
> - emit_stx(pprog, bpf_size, dst_reg, src_reg, off);
> + emit_stx(pprog, BPF_SIZE(insn->code), dst_reg, src_reg,
> + insn->off);
> break;
> default:
> pr_err("bpf_jit: unknown atomic load/store opcode %02x\n",
> @@ -1904,6 +1917,7 @@ static int do_jit(struct bpf_verifier_env *env, struct bpf_prog *bpf_prog, int *
> const s32 imm32 = insn->imm;
> u32 dst_reg = insn->dst_reg;
> u32 src_reg = insn->src_reg;
> + bool accesses_stack_only;
> u8 b2 = 0, b3 = 0;
> u8 *start_of_ldx;
> s64 jmp_offset;
> @@ -1924,6 +1938,8 @@ static int do_jit(struct bpf_verifier_env *env, struct bpf_prog *bpf_prog, int *
> EMIT_ENDBR();
>
> ip = image + addrs[i - 1] + (prog - temp);
> + accesses_stack_only =
> + bpf_insn_accesses_stack_only(env, bpf_prog, i - 1);
>
> switch (insn->code) {
> /* ALU */
> @@ -2304,6 +2320,10 @@ static int do_jit(struct bpf_verifier_env *env, struct bpf_prog *bpf_prog, int *
> case BPF_ST | BPF_MEM | BPF_H:
> case BPF_ST | BPF_MEM | BPF_W:
> case BPF_ST | BPF_MEM | BPF_DW:
> + err = emit_kasan_check(&prog, dst_reg, insn, ip, true,
> + accesses_stack_only);
> + if (err)
> + return err;
> switch (BPF_SIZE(insn->code)) {
> case BPF_B:
> if (is_ereg(dst_reg))
> @@ -2369,6 +2389,10 @@ static int do_jit(struct bpf_verifier_env *env, struct bpf_prog *bpf_prog, int *
> insn_off = outgoing_arg_base - outgoing_rsp - insn_off - 16;
> dst_reg = BPF_REG_FP;
> }
> + err = emit_kasan_check(&prog, dst_reg, insn, ip, true,
> + accesses_stack_only);
> + if (err)
> + return err;
> emit_stx(&prog, BPF_SIZE(insn->code), dst_reg, src_reg, insn_off);
> break;
>
> @@ -2530,6 +2554,12 @@ static int do_jit(struct bpf_verifier_env *env, struct bpf_prog *bpf_prog, int *
> /* populate jmp_offset for JAE above to jump to start_of_ldx */
> start_of_ldx = prog;
> end_of_jmp[-1] = start_of_ldx - end_of_jmp;
> + } else {
> + err = emit_kasan_check(&prog, src_reg, insn, ip,
> + false,
> + accesses_stack_only);
> + if (err)
> + return err;
> }
> if (BPF_MODE(insn->code) == BPF_PROBE_MEMSX ||
> BPF_MODE(insn->code) == BPF_MEMSX)
> @@ -2592,13 +2622,13 @@ static int do_jit(struct bpf_verifier_env *env, struct bpf_prog *bpf_prog, int *
> fallthrough;
> case BPF_STX | BPF_ATOMIC | BPF_W:
> case BPF_STX | BPF_ATOMIC | BPF_DW:
> + bool is64 = BPF_SIZE(insn->code) == BPF_DW;
> + u32 real_src_reg = src_reg;
> + u32 real_dst_reg = dst_reg;
With llvm23, I got the following build failure:
/home/yhs/work/bpf-next/arch/x86/net/bpf_jit_comp.c:2625:4: error:
label followed by a declaration is a C23 extension [-Werror,-Wc23-extensions]
2625 | bool is64 = BPF_SIZE(insn->code) == BPF_DW;
| ^
1 error generated.
The below is a fix:
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index cb3c03edc4bd..61faf8d8f157 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -2621,7 +2621,7 @@ static int do_jit(struct bpf_verifier_env *env, struct bpf_prog *bpf_prog, int *
}
fallthrough;
case BPF_STX | BPF_ATOMIC | BPF_W:
- case BPF_STX | BPF_ATOMIC | BPF_DW:
+ case BPF_STX | BPF_ATOMIC | BPF_DW: {
bool is64 = BPF_SIZE(insn->code) == BPF_DW;
u32 real_src_reg = src_reg;
u32 real_dst_reg = dst_reg;
@@ -2695,6 +2695,7 @@ static int do_jit(struct bpf_verifier_env *env, struct bpf_prog *bpf_prog, int *
if (err)
return err;
break;
+ }
case BPF_STX | BPF_PROBE_ATOMIC | BPF_B:
case BPF_STX | BPF_PROBE_ATOMIC | BPF_H:
> + u8 *branch_target;
> if (insn->imm == (BPF_AND | BPF_FETCH) ||
> insn->imm == (BPF_OR | BPF_FETCH) ||
> insn->imm == (BPF_XOR | BPF_FETCH)) {
> - bool is64 = BPF_SIZE(insn->code) == BPF_DW;
> - u32 real_src_reg = src_reg;
> - u32 real_dst_reg = dst_reg;
> - u8 *branch_target;
>
> /*
> * Can't be implemented with a single x86 insn.
> @@ -2612,7 +2642,19 @@ static int do_jit(struct bpf_verifier_env *env, struct bpf_prog *bpf_prog, int *
> if (dst_reg == BPF_REG_0)
> real_dst_reg = BPF_REG_AX;
>
> + ip += 3;
> + }
> + if (!bpf_atomic_is_load_store(insn)) {
> + err = emit_kasan_check(&prog, real_dst_reg,
> + insn, ip, false,
> + accesses_stack_only);
> + if (err)
> + return err;
> branch_target = prog;
> + }
> + if (insn->imm == (BPF_AND | BPF_FETCH) ||
> + insn->imm == (BPF_OR | BPF_FETCH) ||
> + insn->imm == (BPF_XOR | BPF_FETCH)) {
> /* Load old value */
> emit_ldx(&prog, BPF_SIZE(insn->code),
> BPF_REG_0, real_dst_reg, insn->off);
> @@ -2644,8 +2686,9 @@ static int do_jit(struct bpf_verifier_env *env, struct bpf_prog *bpf_prog, int *
> }
>
> if (bpf_atomic_is_load_store(insn))
> - err = emit_atomic_ld_st(&prog, insn->imm, dst_reg, src_reg,
> - insn->off, BPF_SIZE(insn->code));
> + err = emit_atomic_ld_st(&prog, insn, ip,
> + dst_reg, src_reg,
> + accesses_stack_only);
> else
> err = emit_atomic_rmw(&prog, insn->imm, dst_reg, src_reg,
> insn->off, BPF_SIZE(insn->code));
>
^ permalink raw reply related
* Re: [PATCH net-next v2 13/14] net: stmmac: tc956x: add TC956x/QPS615 support
From: Rob Herring @ 2026-06-05 14:47 UTC (permalink / raw)
To: Alex Elder
Cc: andrew+netdev, davem, edumazet, kuba, pabeni, maxime.chevallier,
rmk+kernel, andersson, konradybcio, krzk+dt, conor+dt, linusw,
brgl, arnd, gregkh, Daniel Thompson, mohd.anwar, a0987203069,
alexandre.torgue, ast, boon.khai.ng, chenchuangyu, chenhuacai,
daniel, hawk, hkallweit1, inochiama, john.fastabend, julianbraha,
livelycarpet87, mcoquelin.stm32, me, prabhakar.mahadev-lad.rj,
richardcochran, rohan.g.thomas, sdf, siyanteng, weishangjuan,
wens, netdev, bpf, linux-arm-msm, devicetree, linux-gpio,
linux-stm32, linux-arm-kernel, linux-kernel
In-Reply-To: <20260605010022.968612-14-elder@riscstar.com>
On Thu, Jun 04, 2026 at 08:00:20PM -0500, Alex Elder wrote:
> From: Daniel Thompson <daniel@riscstar.com>
>
> Toshiba TC956x is an Ethernet AVB/TSN bridge and is essentially a
> small and highly-specialized SoC. TC956x includes an "eMAC" subsystem
> that can be accessed, along with several other peripherals, via two
> PCIe endpoint functions. There is a main driver for the endpoint that
> decomposes things and creates auxiliary bus devices to model the SoC.
>
> The eMAC consists of a Designware XGMAC, XPCS and PMA. Each eMAC is
> supported by an MSIGEN that bridges TC956x level interrupts to PCIe
> MSIs.
>
> Add a driver for the eMAC/MSIGEN combination.
>
> Co-developed-by: Alex Elder <elder@riscstar.com>
> Signed-off-by: Alex Elder <elder@riscstar.com>
> Signed-off-by: Daniel Thompson <daniel@riscstar.com>
The order is wrong here unless you worked on it and then Daniel took
over. Tags should be chronological order.
> ---
> MAINTAINERS | 2 +
> drivers/net/ethernet/stmicro/stmmac/Kconfig | 14 +
> drivers/net/ethernet/stmicro/stmmac/Makefile | 2 +
> .../ethernet/stmicro/stmmac/dwmac-tc956x.c | 818 ++++++++++++++++++
> 4 files changed, 836 insertions(+)
> create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-tc956x.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 0439607d1155f..418537cbefbbb 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -27059,6 +27059,8 @@ S: Maintained
> F: Documentation/devicetree/bindings/net/toshiba,tc956x-dwmac.yaml
> F: drivers/gpio/gpio-tc956x.c
> F: drivers/misc/tc956x_pci.c
> +F: drivers/net/ethernet/stmicro/stmmac/dwmac-tc956x.c
> +F: include/soc/toshiba/tc956x-dwmac.h
>
> TOSHIBA WMI HOTKEYS DRIVER
> M: Azael Avalos <coproscefalo@gmail.com>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
> index e3dd5adda5aca..8d247e033e356 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
> +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
> @@ -404,6 +404,20 @@ config DWMAC_MOTORCOMM
> This enables glue driver for Motorcomm DWMAC-based PCI Ethernet
> controllers. Currently only YT6801 is supported.
>
> +config DWMAC_TC956X
> + tristate "Toshiba TC956X DWMAC support"
> + depends on PCI
> + depends on COMMON_CLK
> + depends on TOSHIBA_TC956X_PCI
> + default TOSHIBA_TC956X_PCI
> + select GENERIC_IRQ_CHIP
> + help
> + This selects the Toshiba TC956X (and Qualcomm QPS615) support in the
> + stmmac driver.
> +
> + This provides support for the ethernet controllers found on these
> + devices.
> +
> config STMMAC_PCI
> tristate "STMMAC PCI bus support"
> depends on PCI
> diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
> index a1cea2f57252e..e8e7f95dbe3e8 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/Makefile
> +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
> @@ -51,4 +51,6 @@ obj-$(CONFIG_STMMAC_PCI) += stmmac-pci.o
> obj-$(CONFIG_DWMAC_INTEL) += dwmac-intel.o
> obj-$(CONFIG_DWMAC_LOONGSON) += dwmac-loongson.o
> obj-$(CONFIG_DWMAC_MOTORCOMM) += dwmac-motorcomm.o
> +obj-$(CONFIG_TC956X_PCI) += tc956x-pci.o
> +obj-$(CONFIG_DWMAC_TC956X) += dwmac-tc956x.o
> stmmac-pci-objs:= stmmac_pci.o
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-tc956x.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-tc956x.c
> new file mode 100644
> index 0000000000000..c77585e4a50e6
> --- /dev/null
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-tc956x.c
> @@ -0,0 +1,818 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +/*
> + * Copyright (C) 2026 by RISCstar Solutions Corporation. All rights reserved.
> + *
> + * Derived from code having the following copyrights:
> + * Copyright (C) 2011-2012 Vayavya Labs Pvt Ltd
> + * Copyright (C) 2025 Toshiba Electronic Devices & Storage Corporation
> + */
> +
> +#include <linux/auxiliary_bus.h>
Based on the block diagram, these are PCI devices. Auxiliary bus is the
wrong thing to use here.
Rob
^ permalink raw reply
* [PATCH v2] arm64: errata: Workaround NVIDIA Olympus device store/load ordering erratum
From: Shanker Donthineni @ 2026-06-05 14:45 UTC (permalink / raw)
To: Catalin Marinas, Will Deacon, linux-arm-kernel, Vladimir Murzin
Cc: Mark Rutland, linux-kernel, linux-doc, Shanker Donthineni,
Vikram Sethi, Jason Sequeira
On systems with NVIDIA Olympus cores, a Device-nGnR* load can be
observed by a peripheral before an older, non-overlapping Device-nGnR*
store to the same peripheral. This breaks the program-order guarantee
that software expects for Device-nGnR* accesses and can leave a
peripheral in an incorrect state, as a load is observed before an
earlier store takes effect.
The erratum can occur only when all of the following apply:
- A PE executes a Device-nGnR* store followed by a younger
Device-nGnR* load.
- The store is not a store-release.
- The accesses target the same peripheral and do not overlap in bytes.
- There is at most one intervening Device-nGnR* store in program
order, and there are no intervening Device-nGnR* loads.
- There is no DSB, and no DMB that orders loads, between the store and
the load.
- Specific micro-architectural and timing conditions occur.
Two ways to restore ordering: insert a barrier (any DSB, or a DMB that
orders loads) between the store and the load, or make the store a
store-release. A load-acquire on the load side would not help, because
acquire semantics do not prevent a load from being observed ahead of an
older store; only the store side (release or a barrier) closes the
window.
Promote the raw MMIO store helpers (__raw_writeb/w/l/q) from plain str*
to stlr* (Store-Release), which removes the "store is not a
store-release" condition for every device write the kernel issues.
Because writel() and writel_relaxed() are both built on __raw_writel()
in asm-generic/io.h, patching the raw variants covers both the
non-relaxed and relaxed APIs without touching the higher layers. Note
that writel()'s own barrier sits before the store, so it does not order
the store against a subsequent readl(); the store-release promotion is
what provides that ordering.
Like ARM64_ERRATUM_832075 on the load side, the change is gated on a new
ARM64_WORKAROUND_DEVICE_STORE_RELEASE capability and only activated on
parts that match MIDR_NVIDIA_OLYMPUS, so unaffected CPUs continue to use
the plain str* sequence.
Note: stlr* only supports base-register addressing, so the raw accessors
can no longer use the offset addressing introduced by commit d044d6ba6f02
("arm64: io: permit offset addressing"). The str* and stlr* alternates
share a single inline-asm operand and the sequence is selected at boot,
so the operand form is fixed at compile time; unaffected CPUs keep using
str* but also revert to base-register addressing. This keeps the store
side as simple as the existing load-side patching (load-acquire) and
avoids adding complexity to the device write path; retaining offset
addressing only for str* would otherwise require a runtime branch on
every write.
Co-developed-by: Vikram Sethi <vsethi@nvidia.com>
Signed-off-by: Vikram Sethi <vsethi@nvidia.com>
Signed-off-by: Shanker Donthineni <sdonthineni@nvidia.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
---
Changes since v1:
Update commit text based on feedback from Vladimir Murzin
Documentation/arch/arm64/silicon-errata.rst | 2 ++
arch/arm64/Kconfig | 23 ++++++++++++++++++++
arch/arm64/include/asm/io.h | 24 ++++++++++++++-------
arch/arm64/kernel/cpu_errata.c | 8 +++++++
arch/arm64/tools/cpucaps | 1 +
5 files changed, 50 insertions(+), 8 deletions(-)
diff --git a/Documentation/arch/arm64/silicon-errata.rst b/Documentation/arch/arm64/silicon-errata.rst
index 211119ce7adc..899bed3908bb 100644
--- a/Documentation/arch/arm64/silicon-errata.rst
+++ b/Documentation/arch/arm64/silicon-errata.rst
@@ -256,6 +256,8 @@ stable kernels.
+----------------+-----------------+-----------------+-----------------------------+
| NVIDIA | Carmel Core | N/A | NVIDIA_CARMEL_CNP_ERRATUM |
+----------------+-----------------+-----------------+-----------------------------+
+| NVIDIA | Olympus core | T410-OLY-1027 | NVIDIA_OLYMPUS_1027_ERRATUM |
++----------------+-----------------+-----------------+-----------------------------+
| NVIDIA | T241 GICv3/4.x | T241-FABRIC-4 | N/A |
+----------------+-----------------+-----------------+-----------------------------+
| NVIDIA | T241 MPAM | T241-MPAM-1 | N/A |
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index fe60738e5943..a6bac84b05a1 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -564,6 +564,29 @@ config ARM64_ERRATUM_832075
If unsure, say Y.
+config NVIDIA_OLYMPUS_1027_ERRATUM
+ bool "NVIDIA Olympus: device store/load ordering erratum"
+ default y
+ help
+ This option adds an alternative code sequence to work around an
+ NVIDIA Olympus core erratum where a Device-nGnR* store can be
+ observed by a peripheral after a younger Device-nGnR* load to the
+ same peripheral. This breaks the program order that drivers rely
+ on for MMIO and can leave a device in an incorrect state.
+
+ The workaround promotes the raw MMIO store helpers
+ (__raw_writeb/w/l/q) to Store-Release (STLR), which restores the
+ required ordering. Because writel() and writel_relaxed() are built
+ on __raw_writel(), both are covered without changes to the higher
+ layers.
+
+ The fix is applied through the alternatives framework, so enabling
+ this option does not by itself activate the workaround: it is
+ patched in only when an affected CPU is detected, and is a no-op on
+ unaffected CPUs.
+
+ If unsure, say Y.
+
config ARM64_ERRATUM_834220
bool "Cortex-A57: 834220: Stage 2 translation fault might be incorrectly reported in presence of a Stage 1 fault (rare)"
depends on KVM
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
index 8cbd1e96fd50..b6d7966e9c19 100644
--- a/arch/arm64/include/asm/io.h
+++ b/arch/arm64/include/asm/io.h
@@ -25,29 +25,37 @@
#define __raw_writeb __raw_writeb
static __always_inline void __raw_writeb(u8 val, volatile void __iomem *addr)
{
- volatile u8 __iomem *ptr = addr;
- asm volatile("strb %w0, %1" : : "rZ" (val), "Qo" (*ptr));
+ asm volatile(ALTERNATIVE("strb %w0, [%1]",
+ "stlrb %w0, [%1]",
+ ARM64_WORKAROUND_DEVICE_STORE_RELEASE)
+ : : "rZ" (val), "r" (addr));
}
#define __raw_writew __raw_writew
static __always_inline void __raw_writew(u16 val, volatile void __iomem *addr)
{
- volatile u16 __iomem *ptr = addr;
- asm volatile("strh %w0, %1" : : "rZ" (val), "Qo" (*ptr));
+ asm volatile(ALTERNATIVE("strh %w0, [%1]",
+ "stlrh %w0, [%1]",
+ ARM64_WORKAROUND_DEVICE_STORE_RELEASE)
+ : : "rZ" (val), "r" (addr));
}
#define __raw_writel __raw_writel
static __always_inline void __raw_writel(u32 val, volatile void __iomem *addr)
{
- volatile u32 __iomem *ptr = addr;
- asm volatile("str %w0, %1" : : "rZ" (val), "Qo" (*ptr));
+ asm volatile(ALTERNATIVE("str %w0, [%1]",
+ "stlr %w0, [%1]",
+ ARM64_WORKAROUND_DEVICE_STORE_RELEASE)
+ : : "rZ" (val), "r" (addr));
}
#define __raw_writeq __raw_writeq
static __always_inline void __raw_writeq(u64 val, volatile void __iomem *addr)
{
- volatile u64 __iomem *ptr = addr;
- asm volatile("str %x0, %1" : : "rZ" (val), "Qo" (*ptr));
+ asm volatile(ALTERNATIVE("str %x0, [%1]",
+ "stlr %x0, [%1]",
+ ARM64_WORKAROUND_DEVICE_STORE_RELEASE)
+ : : "rZ" (val), "r" (addr));
}
#define __raw_readb __raw_readb
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 5377e4c2eba2..958d7f16bfeb 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -809,6 +809,14 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
ERRATA_MIDR_ALL_VERSIONS(MIDR_NVIDIA_CARMEL),
},
#endif
+#ifdef CONFIG_NVIDIA_OLYMPUS_1027_ERRATUM
+ {
+ /* NVIDIA Olympus core */
+ .desc = "NVIDIA Olympus device load/store ordering erratum",
+ .capability = ARM64_WORKAROUND_DEVICE_STORE_RELEASE,
+ ERRATA_MIDR_ALL_VERSIONS(MIDR_NVIDIA_OLYMPUS),
+ },
+#endif
#ifdef CONFIG_ARM64_WORKAROUND_TRBE_OVERWRITE_FILL_MODE
{
/*
diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps
index 811c2479e82d..d367257bf770 100644
--- a/arch/arm64/tools/cpucaps
+++ b/arch/arm64/tools/cpucaps
@@ -120,6 +120,7 @@ WORKAROUND_CAVIUM_TX2_219_PRFM
WORKAROUND_CAVIUM_TX2_219_TVM
WORKAROUND_CLEAN_CACHE
WORKAROUND_DEVICE_LOAD_ACQUIRE
+WORKAROUND_DEVICE_STORE_RELEASE
WORKAROUND_NVIDIA_CARMEL_CNP
WORKAROUND_PMUV3_IMPDEF_TRAPS
WORKAROUND_QCOM_FALKOR_E1003
--
2.43.0
^ permalink raw reply related
* Re: [PATCH v3 3/3] iommu/arm-smmu-v3: Issue CFGI/TLBI twice on Tegra264
From: Ashish Mhetre @ 2026-06-05 14:41 UTC (permalink / raw)
To: Will Deacon, Jason Gunthorpe
Cc: robin.murphy, joro, nicolinc, linux-arm-kernel, iommu,
linux-kernel, linux-tegra
In-Reply-To: <aiAQ9ApqfTsdweRg@willie-the-truck>
On 6/3/2026 5:03 PM, Will Deacon wrote:
> External email: Use caution opening links or attachments
>
>
> On Tue, Jun 02, 2026 at 10:01:14PM -0300, Jason Gunthorpe wrote:
>> On Tue, Jun 02, 2026 at 09:22:15PM +0100, Will Deacon wrote:
>>>> + /*
>>>> + * On Tegra264 (see ARM_SMMU_OPT_TLBI_TWICE) re-issue the same
>>>> + * cmdlist with another CMD_SYNC to satisfy the erratum.
>>>> + * Callers must ensure the batch carries a uniform opcode class
>>>> + * so that checking the first command is enough; the iommufd
>>>> + * VSMMU path enforces this with arm_vsmmu_can_batch_cmd().
>>>> + */
>>>> + if (!ret && sync && arm_smmu_cmd_needs_tlbi_twice(smmu, &cmds[0]))
>>> Can you move the arm_smmu_cmd_... part to the start of the conjunction,
>>> please? If you make it a static key as I mentioned previously, then
>>> hopefully that should mean everything else is moved out of line.
>>>
>>>> + ret = __arm_smmu_cmdq_issue_cmdlist(smmu, cmdq, cmds, n, sync);
>>> Sashiko is also unhappy here if n == 0 because we probably shouldn't
>>> be inspecting the command array in that case.
>> That seems like an AI mistake though, we shouldn't actually ever pass
>> in 0 sized batches? 'zero streams' should fail probe, not get into
>> this code, that might be missing but I wouldn't add checks here..
> I was wondering about the case where the first command in a batch is
> unsupported. Can we issue a bare sync in that case?
Seems a valid case. But considering the static branch approach, will
it be fine to add "n != 0" check before arm_smmu_cmd_needs_tlbi_twice()
? Something like: int ret = __arm_smmu_cmdq_issue_cmdlist(smmu, cmdq,
cmds, n, sync);
if(!n) return ret; if (arm_smmu_erratum_cmd_needs_repeating(smmu,
&cmds[0]) && !ret && sync) ret = __arm_smmu_cmdq_issue_cmdlist(smmu,
cmdq, cmds, n, sync);
> Will
Thanks,
Ashish Mhetre
^ permalink raw reply
* Re: [PATCH net-next v2 10/14] dt-bindings: net: toshiba,tc9654-dwmac: add TC9564 Ethernet bridge
From: Rob Herring @ 2026-06-05 14:40 UTC (permalink / raw)
To: Alex Elder
Cc: andrew+netdev, davem, edumazet, kuba, pabeni, maxime.chevallier,
rmk+kernel, andersson, konradybcio, krzk+dt, conor+dt, linusw,
brgl, arnd, gregkh, Daniel Thompson, mohd.anwar, a0987203069,
alexandre.torgue, ast, boon.khai.ng, chenchuangyu, chenhuacai,
daniel, hawk, hkallweit1, inochiama, john.fastabend, julianbraha,
livelycarpet87, mcoquelin.stm32, me, prabhakar.mahadev-lad.rj,
richardcochran, rohan.g.thomas, sdf, siyanteng, weishangjuan,
wens, netdev, bpf, linux-arm-msm, devicetree, linux-gpio,
linux-stm32, linux-arm-kernel, linux-kernel
In-Reply-To: <20260605010022.968612-11-elder@riscstar.com>
On Thu, Jun 04, 2026 at 08:00:17PM -0500, Alex Elder wrote:
> From: Daniel Thompson <daniel@riscstar.com>
>
> Add devicetree bindings for the Toshiba TC956x family of Ethernet-AVB/TSN
> bridges.
>
> The TC9564 contains a PCIe switch with one upstream and three downstream
> PCIe ports. The third PCIe downstream port has an attached embedded PCIe
> endpoint, and that endpoint implements two PCIe functions. Each internal
> PCIe function has a Synopsys XGMAC Ethernet interface capable of 10 Gbps
> operation.
>
> The TC9564 also implements an embedded GPIO controller, which exposes
> 10 lines externally. Some platforms use these GPIO lines, so this
> GPIO controller is managed by a separate driver. Other embedded
> peripherals (like a microcontroller, SRAM, and UART) are currently
> unused.
>
> The GPIO controller is managed by registers accessed via MMIO on an
> internal PCIe function's registers.
>
> Signed-off-by: Daniel Thompson <daniel@riscstar.com>
> Signed-off-by: Alex Elder <elder@riscstar.com>
> ---
> .../bindings/net/toshiba,tc9564-dwmac.yaml | 120 ++++++++++++++++++
> MAINTAINERS | 6 +
> 2 files changed, 126 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/net/toshiba,tc9564-dwmac.yaml
>
> diff --git a/Documentation/devicetree/bindings/net/toshiba,tc9564-dwmac.yaml b/Documentation/devicetree/bindings/net/toshiba,tc9564-dwmac.yaml
> new file mode 100644
> index 0000000000000..6e7a63dfcf86a
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/toshiba,tc9564-dwmac.yaml
> @@ -0,0 +1,120 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/net/toshiba,tc9564-dwmac.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Toshiba TC956x Ethernet-AVB/TSN Controller
> +
> +maintainers:
> + - Alex Elder <elder@riscstar.com>
> + - Daniel Thompson <daniel@riscstar.com>
> +
> +description: |
> + The Toshiba TC9564 (and more generally, TC956x) incorporates a PCIe
> + gen 3 switch with one upstream and three downstream ports. The first
> + two downstream ports are exposed externally, while the third is used
> + by an internal PCIe endpoint. The PCIe endpoint implements two PCIe
> + functions, and attached to each of these is a 10 Gbps capable Synopsys
> + Ethernet controller.
> +
> + The TC956x additionally implements other internal IP blocks, and in
> + particular it implements a GPIO controller. Ten of the 35 GPIO lines
> + implemented are exposed externally and are usable by the platform.
> + It is platform-dependent whether the GPIO function must be exposed,
> + and if it is, PCIe function 0 supplies it.
> +
> + ----------------------------------
> + | Host |
> + ------+...+----------+........+---
> + |i2c| | PCIe |
> + ----------------+...+----------+........+------
> + | TC956x |I2C| |upstream| |
> + | ----- --+--------+--- |
> + | ----- ------ ------- | PCIe switch | |
> + | |SPI| |GPIO| |reset| | | |
> + | ----- ------ |clock| | DS3 DS2 DS1 | |
> + | ------- ---++--++--++-- |
> + | ----- ------ downstream// \\ \\ | downstream
> + | |MCU| |SRAM| /==========/ \\ \===== PCIe port 1
> + | ----- ------ //PCIe port 3 \\ |
> + | || \======= downstream
> + | ----+-----------++-----------+---- | PCIe port 2
> + | | M | internal PCIe endpoint | M | |
> + | | S |------------------------| S | ------ |
> + | | I | PCIe | | PCIe | I | |UART| |
> + | | G |function 0| |function 1| G | ------ |
I don't see nodes for these PCI functions. Boot this platform with
CONFIG_PCI_DYNAMIC_OF_NODES enabled and use the resulting DT node
structure. Anything else is wrong. This will give you the DTS:
dtc -O dts /proc/device-tree
The ethernet nodes should be just these PCI function nodes. You need to
make the DWMAC PCI driver (stmmac_pci.c) bind to those 2 PCI devices.
And really, a DT node for them should be completely optional (unless
there's some power on ctrl needed).
Everything else like SPI, GPIO, UART, etc. should be under the PCIe
switch upstream node in a pci-ep-bus.
> + | | E |----++----| |----++----| E | |
> + | | N | eMAC 0 | | eMAC 1 | N | |
> + --------+.......+------+.....+-----------------
> + |USXGMII| |SGMII|
> + --+.......+-- --+.....+--
> + | ARQ113C | | QEP8121 |
> + | PHY | | PHY |
> + ------------- -----------
> +
> +properties:
> + compatible:
> + enum:
> + - pci1179,0220 # Toshiba TC9564 (a.k.a. Qualcomm QPS615)
> +
> + gpio:
> + type: object
> + description: Embedded GPIO controller
> + $ref: /schemas/gpio/gpio.yaml#
gpio.yaml alone does not define a GPIO controller. How many #gpio-cells
needs to be defined.
Is there no address associated with the controller?
> +
> + ethernet:
> + type: object
> + description: XGMAC Ethernet controller
> + $ref: /schemas/net/ethernet-controller.yaml#
> + properties:
> + mdio:
> + $ref: snps,dwmac.yaml#/properties/mdio
Either all of snps,dwmac.yaml should apply or none of it. Generally, we
only reference whole schema files (OF graph being a notable exception).
> + required:
> + - mdio
> +
> +required:
> + - compatible
> +
> +allOf:
> + - $ref: /schemas/pci/pci-device.yaml#
> + - $ref: /schemas/pci/pci-bus-common.yaml#
These 2 are just pci-pci-bridge.yaml.
Rob
^ permalink raw reply
* Re: [PATCH 71/76] drm/xlnx: zynqmp_dp: Switch to atomic_create_state
From: Laurent Pinchart @ 2026-06-05 14:39 UTC (permalink / raw)
To: Maxime Ripard
Cc: Andrzej Hajda, Neil Armstrong, Robert Foss, Jonas Karlman,
Jernej Skrabec, Luca Ceresoli, Maarten Lankhorst,
Thomas Zimmermann, David Airlie, Simona Vetter, Dmitry Baryshkov,
dri-devel, Tomi Valkeinen, Michal Simek, linux-arm-kernel
In-Reply-To: <20260530-drm-no-more-bridge-reset-v1-71-875d828d31bc@kernel.org>
On Sat, May 30, 2026 at 04:00:16PM +0200, Maxime Ripard wrote:
> The drm_bridge_funcs.atomic_reset callback and its
> drm_atomic_helper_bridge_reset() helper are deprecated.
>
> Switch to the atomic_create_state callback and its
> drm_atomic_helper_bridge_create_state() counterpart.
>
> Signed-off-by: Maxime Ripard <mripard@kernel.org>
Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
> To: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> To: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
> To: Michal Simek <michal.simek@amd.com>
> Cc: dri-devel@lists.freedesktop.org
> Cc: linux-arm-kernel@lists.infradead.org
> ---
> drivers/gpu/drm/xlnx/zynqmp_dp.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/xlnx/zynqmp_dp.c b/drivers/gpu/drm/xlnx/zynqmp_dp.c
> index 7fb11b0a44f0..b209582bc130 100644
> --- a/drivers/gpu/drm/xlnx/zynqmp_dp.c
> +++ b/drivers/gpu/drm/xlnx/zynqmp_dp.c
> @@ -2278,11 +2278,11 @@ static const struct drm_bridge_funcs zynqmp_dp_bridge_funcs = {
> .mode_valid = zynqmp_dp_bridge_mode_valid,
> .atomic_enable = zynqmp_dp_bridge_atomic_enable,
> .atomic_disable = zynqmp_dp_bridge_atomic_disable,
> .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
> .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
> - .atomic_reset = drm_atomic_helper_bridge_reset,
> + .atomic_create_state = drm_atomic_helper_bridge_create_state,
> .atomic_check = zynqmp_dp_bridge_atomic_check,
> .detect = zynqmp_dp_bridge_detect,
> .edid_read = zynqmp_dp_bridge_edid_read,
> .atomic_get_input_bus_fmts = zynqmp_dp_bridge_get_input_bus_fmts,
> .debugfs_init = zynqmp_dp_bridge_debugfs_init,
--
Regards,
Laurent Pinchart
^ permalink raw reply
* Re: [PATCH v01] mailbox/pcc.c: add query channel function
From: kernel test robot @ 2026-06-05 14:39 UTC (permalink / raw)
To: Adam Young, Sudeep Holla, Jassi Brar, Rafael J. Wysocki,
Saket Dumbre, Len Brown
Cc: llvm, oe-kbuild-all, linux-kernel, linux-hwmon, linux-acpi,
Andi Shyti, Guenter Roeck, Huisong Li, MyungJoo Ham,
Kyungmin Park, Chanwoo Choi, linux-arm-kernel
In-Reply-To: <20260604203749.168752-1-admiyo@os.amperecomputing.com>
Hi Adam,
kernel test robot noticed the following build warnings:
[auto build test WARNING on jassibrar-mailbox/for-next]
[also build test WARNING on rafael-pm/linux-next rafael-pm/bleeding-edge soc/for-next linus/master v7.1-rc6 next-20260603]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Adam-Young/mailbox-pcc-c-add-query-channel-function/20260605-044323
base: https://git.kernel.org/pub/scm/linux/kernel/git/jassibrar/mailbox.git for-next
patch link: https://lore.kernel.org/r/20260604203749.168752-1-admiyo%40os.amperecomputing.com
patch subject: [PATCH v01] mailbox/pcc.c: add query channel function
config: riscv-allyesconfig (https://download.01.org/0day-ci/archive/20260605/202606052232.LAlOTWJr-lkp@intel.com/config)
compiler: clang version 23.0.0git (https://github.com/llvm/llvm-project 7917772d7d61384696c61102c08c2ea158e610fa)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260605/202606052232.LAlOTWJr-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202606052232.LAlOTWJr-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> Warning: drivers/mailbox/pcc.c:358 function parameter 'q_chan' not described in 'pcc_mbox_query_channel'
>> Warning: drivers/mailbox/pcc.c:358 function parameter 'subspace_id' not described in 'pcc_mbox_query_channel'
>> Warning: drivers/mailbox/pcc.c:358 function parameter 'q_chan' not described in 'pcc_mbox_query_channel'
>> Warning: drivers/mailbox/pcc.c:358 function parameter 'subspace_id' not described in 'pcc_mbox_query_channel'
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* Re: [PATCH v14 29/44] arm64: RMI: Runtime faulting of memory
From: Lorenzo Pieralisi @ 2026-06-05 14:35 UTC (permalink / raw)
To: Gavin Shan
Cc: Steven Price, kvm, kvmarm, Catalin Marinas, Marc Zyngier,
Will Deacon, James Morse, Oliver Upton, Suzuki K Poulose,
Zenghui Yu, linux-arm-kernel, linux-kernel, Joey Gouly,
Alexandru Elisei, Christoffer Dall, Fuad Tabba, linux-coco,
Ganapatrao Kulkarni, Shanker Donthineni, Alper Gun,
Aneesh Kumar K . V, Emi Kisanuki, Vishal Annapurve, WeiLin.Chang,
Lorenzo.Pieralisi2
In-Reply-To: <ecef952b-e8c6-4102-933b-c99c46f14431@redhat.com>
On Fri, Jun 05, 2026 at 06:11:11PM +1000, Gavin Shan wrote:
> On 6/5/26 5:28 PM, Lorenzo Pieralisi wrote:
> > On Fri, Jun 05, 2026 at 04:23:15PM +1000, Gavin Shan wrote:
> >
> > [...]
> >
> > > > +static int realm_map_ipa(struct kvm *kvm, phys_addr_t ipa,
> > > > + kvm_pfn_t pfn, unsigned long map_size,
> > > > + enum kvm_pgtable_prot prot,
> > > > + struct kvm_mmu_memory_cache *memcache)
> > > > +{
> > > > + struct realm *realm = &kvm->arch.realm;
> > > > +
> > > > + /*
> > > > + * Write permission is required for now even though it's possible to
> > > > + * map unprotected pages (granules) as read-only. It's impossible to
> > > > + * map protected pages (granules) as read-only.
> > > > + */
> > > > + if (WARN_ON(!(prot & KVM_PGTABLE_PROT_W)))
> > > > + return -EFAULT;
> > > > +
> > >
> > > I'm a bit concerned with this. We don't have KVM_PGTABLE_PROT_W set in @prot
> > > if the stage2 fault is raised due to memory read. With -EFAULT returned to VMM
> > > (e.g. QEMU), the vCPU continuous execution is stopped and system won't be
> > > working any more.
> > >
> > > > + ipa = ALIGN_DOWN(ipa, PAGE_SIZE);
> > > > + if (!kvm_realm_is_private_address(realm, ipa))
> > > > + return realm_map_non_secure(realm, ipa, pfn, map_size, prot,
> > > > + memcache);
> > > > +
> > > > + return realm_map_protected(kvm, ipa, pfn, map_size, memcache);
> > > > +}
> > > > +
> > > > static bool kvm_vma_is_cacheable(struct vm_area_struct *vma)
> > > > {
> > > > switch (FIELD_GET(PTE_ATTRINDX_MASK, pgprot_val(vma->vm_page_prot))) {
> > > > @@ -1604,27 +1641,52 @@ static int gmem_abort(const struct kvm_s2_fault_desc *s2fd)
> > > > bool write_fault, exec_fault;
> > > > enum kvm_pgtable_walk_flags flags = KVM_PGTABLE_WALK_SHARED;
> > > > enum kvm_pgtable_prot prot = KVM_PGTABLE_PROT_R;
> > > > - struct kvm_pgtable *pgt = s2fd->vcpu->arch.hw_mmu->pgt;
> > > > + struct kvm_vcpu *vcpu = s2fd->vcpu;
> > > > + struct kvm_pgtable *pgt = vcpu->arch.hw_mmu->pgt;
> > > > + gpa_t gpa = kvm_gpa_from_fault(vcpu->kvm, s2fd->fault_ipa);
> > > > unsigned long mmu_seq;
> > > > struct page *page;
> > > > - struct kvm *kvm = s2fd->vcpu->kvm;
> > > > + struct kvm *kvm = vcpu->kvm;
> > > > void *memcache;
> > > > kvm_pfn_t pfn;
> > > > gfn_t gfn;
> > > > int ret;
> > > > - memcache = get_mmu_memcache(s2fd->vcpu);
> > > > - ret = topup_mmu_memcache(s2fd->vcpu, memcache);
> > > > + if (kvm_is_realm(vcpu->kvm)) {
> > > > + /* check for memory attribute mismatch */
> > > > + bool is_priv_gfn = kvm_mem_is_private(kvm, gpa >> PAGE_SHIFT);
> > > > + /*
> > > > + * For Realms, the shared address is an alias of the private
> > > > + * PA with the top bit set. Thus if the fault address matches
> > > > + * the GPA then it is the private alias.
> > > > + */
> > > > + bool is_priv_fault = (gpa == s2fd->fault_ipa);
> > > > +
> > > > + if (is_priv_gfn != is_priv_fault) {
> > > > + kvm_prepare_memory_fault_exit(vcpu, gpa, PAGE_SIZE,
> > > > + kvm_is_write_fault(vcpu),
> > > > + false,
> > > > + is_priv_fault);
> > > > + /*
> > > > + * KVM_EXIT_MEMORY_FAULT requires an return code of
> > > > + * -EFAULT, see the API documentation
> > > > + */
> > > > + return -EFAULT;
> > > > + }
> > > > + }
> > > > +
> > > > + memcache = get_mmu_memcache(vcpu);
> > > > + ret = topup_mmu_memcache(vcpu, memcache);
> > > > if (ret)
> > > > return ret;
> > > > if (s2fd->nested)
> > > > gfn = kvm_s2_trans_output(s2fd->nested) >> PAGE_SHIFT;
> > > > else
> > > > - gfn = s2fd->fault_ipa >> PAGE_SHIFT;
> > > > + gfn = gpa >> PAGE_SHIFT;
> > > > - write_fault = kvm_is_write_fault(s2fd->vcpu);
> > > > - exec_fault = kvm_vcpu_trap_is_exec_fault(s2fd->vcpu);
> > > > + write_fault = kvm_is_write_fault(vcpu);
> > > > + exec_fault = kvm_vcpu_trap_is_exec_fault(vcpu);
> > > > VM_WARN_ON_ONCE(write_fault && exec_fault);
> > > > @@ -1634,7 +1696,7 @@ static int gmem_abort(const struct kvm_s2_fault_desc *s2fd)
> > > > ret = kvm_gmem_get_pfn(kvm, s2fd->memslot, gfn, &pfn, &page, NULL);
> > > > if (ret) {
> > > > - kvm_prepare_memory_fault_exit(s2fd->vcpu, s2fd->fault_ipa, PAGE_SIZE,
> > > > + kvm_prepare_memory_fault_exit(vcpu, gpa, PAGE_SIZE,
> > > > write_fault, exec_fault, false);
> > > > return ret;
> > > > }
> > > > @@ -1654,14 +1716,20 @@ static int gmem_abort(const struct kvm_s2_fault_desc *s2fd)
> > > > kvm_fault_lock(kvm);
> > > > if (mmu_invalidate_retry(kvm, mmu_seq)) {
> > > > ret = -EAGAIN;
> > > > - goto out_unlock;
> > > > + goto out_release_page;
> > > > + }
> > > > +
> > > > + if (kvm_is_realm(kvm)) {
> > > > + ret = realm_map_ipa(kvm, s2fd->fault_ipa, pfn,
> > > > + PAGE_SIZE, KVM_PGTABLE_PROT_R | KVM_PGTABLE_PROT_W, memcache);
> > > > + goto out_release_page;
> > > > }
> > > > ret = KVM_PGT_FN(kvm_pgtable_stage2_map)(pgt, s2fd->fault_ipa, PAGE_SIZE,
> > > > __pfn_to_phys(pfn), prot,
> > > > memcache, flags);
> > > > -out_unlock:
> > > > +out_release_page:
> > > > kvm_release_faultin_page(kvm, page, !!ret, prot & KVM_PGTABLE_PROT_W);
> > > > kvm_fault_unlock(kvm);
> > > > @@ -1847,7 +1915,7 @@ static int kvm_s2_fault_get_vma_info(const struct kvm_s2_fault_desc *s2fd,
> > > > * mapping size to ensure we find the right PFN and lay down the
> > > > * mapping in the right place.
> > > > */
> > > > - s2vi->gfn = ALIGN_DOWN(s2fd->fault_ipa, s2vi->vma_pagesize) >> PAGE_SHIFT;
> > > > + s2vi->gfn = kvm_gpa_from_fault(kvm, ALIGN_DOWN(s2fd->fault_ipa, s2vi->vma_pagesize)) >> PAGE_SHIFT;
> > > > s2vi->mte_allowed = kvm_vma_mte_allowed(vma);
> > > > @@ -2056,6 +2124,9 @@ static int kvm_s2_fault_map(const struct kvm_s2_fault_desc *s2fd,
> > > > prot &= ~KVM_NV_GUEST_MAP_SZ;
> > > > ret = KVM_PGT_FN(kvm_pgtable_stage2_relax_perms)(pgt, gfn_to_gpa(gfn),
> > > > prot, flags);
> > > > + } else if (kvm_is_realm(kvm)) {
> > > > + ret = realm_map_ipa(kvm, s2fd->fault_ipa, pfn, mapping_size,
> > > > + prot, memcache);
> > > > } else {
> > > > ret = KVM_PGT_FN(kvm_pgtable_stage2_map)(pgt, gfn_to_gpa(gfn), mapping_size,
> > > > __pfn_to_phys(pfn), prot,
> > >
> > > For the case kvm_is_realm(), need we adjust 's2fd->fault_ipa' for the sake of
> > > huge pages. In kvm_s2_fault_map(), @gfn and @pfn may have been adjusted by
> > > transparent_hugepage_adjust() to be aligned with huge page size. If the
> > > adjustment happened in transparent_hugepage_adjust(), we need to align
> > > s2fd->fault_ipa down to the huge page size either.
> >
> > All of the above + some RMM changes are needed to get QEmu VMM going
> > with anon pages guest memory backing - currently testing various
> > configurations in the background.
> >
>
> I tried to rebase Jean's latest QEMU series [1] to upstream QEMU, and found
> that memory slots backed by THP are broken. With THP disabled on the host and
> other fixes (mentioned in my prevous replies) applied on the top of this (v14)
> series, I'm able to boot a realm guest with rebased QEMU series [2], plus more
> fxies on the top.
>
> [1] https://git.codelinaro.org/linaro/dcap/qemu.git (branch: cca/latest)
> [2] https://git.qemu.org/git/qemu.git (branch: cca/gavin)
>
> Lorenzo, You may be saying there is someone making QEMU to support ARM/CCA?
Mathieu and I are working on that yes and with Steven/Suzuki to fix the THP
issues you pointed out above.
> If so, I'm not sure if there is a QEMU repository for me to try?
We should be able to submit patches by end of June - we shall let you know
whether we can make something available earlier.
Thanks,
Lorenzo
>
> Thanks,
> Gavin
>
> > Thanks,
> > Lorenzo
> >
> > > > @@ -2214,6 +2285,13 @@ int kvm_handle_guest_sea(struct kvm_vcpu *vcpu)
> > > > return 0;
> > > > }
> > > > +static bool shared_ipa_fault(struct kvm *kvm, phys_addr_t fault_ipa)
> > > > +{
> > > > + gpa_t gpa = kvm_gpa_from_fault(kvm, fault_ipa);
> > > > +
> > > > + return (gpa != fault_ipa);
> > > > +}
> > > > +
> > > > /**
> > > > * kvm_handle_guest_abort - handles all 2nd stage aborts
> > > > * @vcpu: the VCPU pointer
> > > > @@ -2324,8 +2402,9 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu)
> > > > nested = &nested_trans;
> > > > }
> > > > - gfn = ipa >> PAGE_SHIFT;
> > > > + gfn = kvm_gpa_from_fault(vcpu->kvm, ipa) >> PAGE_SHIFT;
> > > > memslot = gfn_to_memslot(vcpu->kvm, gfn);
> > > > +
> > > > hva = gfn_to_hva_memslot_prot(memslot, gfn, &writable);
> > > > write_fault = kvm_is_write_fault(vcpu);
> > > > if (kvm_is_error_hva(hva) || (write_fault && !writable)) {
> > > > @@ -2368,7 +2447,7 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu)
> > > > * of the page size.
> > > > */
> > > > ipa |= FAR_TO_FIPA_OFFSET(kvm_vcpu_get_hfar(vcpu));
> > > > - ret = io_mem_abort(vcpu, ipa);
> > > > + ret = io_mem_abort(vcpu, kvm_gpa_from_fault(vcpu->kvm, ipa));
> > > > goto out_unlock;
> > > > }
> > > > @@ -2396,7 +2475,7 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu)
> > > > !write_fault &&
> > > > !kvm_vcpu_trap_is_exec_fault(vcpu));
> > > > - if (kvm_slot_has_gmem(memslot))
> > > > + if (kvm_slot_has_gmem(memslot) && !shared_ipa_fault(vcpu->kvm, fault_ipa))
> > > > ret = gmem_abort(&s2fd);
> > > > else
> > > > ret = user_mem_abort(&s2fd);
> > > > @@ -2433,6 +2512,10 @@ bool kvm_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
> > > > if (!kvm->arch.mmu.pgt || kvm_vm_is_protected(kvm))
> > > > return false;
> > > > + /* We don't support aging for Realms */
> > > > + if (kvm_is_realm(kvm))
> > > > + return true;
> > > > +
> > > > return KVM_PGT_FN(kvm_pgtable_stage2_test_clear_young)(kvm->arch.mmu.pgt,
> > > > range->start << PAGE_SHIFT,
> > > > size, true);
> > > > @@ -2449,6 +2532,10 @@ bool kvm_test_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
> > > > if (!kvm->arch.mmu.pgt || kvm_vm_is_protected(kvm))
> > > > return false;
> > > > + /* We don't support aging for Realms */
> > > > + if (kvm_is_realm(kvm))
> > > > + return true;
> > > > +
> > > > return KVM_PGT_FN(kvm_pgtable_stage2_test_clear_young)(kvm->arch.mmu.pgt,
> > > > range->start << PAGE_SHIFT,
> > > > size, false);
> > > > @@ -2628,10 +2715,11 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
> > > > return -EFAULT;
> > > > /*
> > > > - * Only support guest_memfd backed memslots with mappable memory, since
> > > > - * there aren't any CoCo VMs that support only private memory on arm64.
> > > > + * Only support guest_memfd backed memslots with mappable memory,
> > > > + * unless the guest is a CCA realm guest.
> > > > */
> > > > - if (kvm_slot_has_gmem(new) && !kvm_memslot_is_gmem_only(new))
> > > > + if (kvm_slot_has_gmem(new) && !kvm_memslot_is_gmem_only(new) &&
> > > > + !kvm_is_realm(kvm))
> > > > return -EINVAL;
> > > > hva = new->userspace_addr;
> > > > diff --git a/arch/arm64/kvm/rmi.c b/arch/arm64/kvm/rmi.c
> > > > index cae29fd3353c..761b38a4071c 100644
> > > > --- a/arch/arm64/kvm/rmi.c
> > > > +++ b/arch/arm64/kvm/rmi.c
> > > > @@ -597,6 +597,179 @@ static int realm_data_map_init(struct kvm *kvm, unsigned long ipa,
> > > > return ret;
> > > > }
> > > > +static unsigned long addr_range_desc(unsigned long phys, unsigned long size)
> > > > +{
> > > > + unsigned long out = 0;
> > > > +
> > > > + switch (size) {
> > > > + case P4D_SIZE:
> > > > + out = 3 | (1 << 2);
> > > > + break;
> > > > + case PUD_SIZE:
> > > > + out = 2 | (1 << 2);
> > > > + break;
> > > > + case PMD_SIZE:
> > > > + out = 1 | (1 << 2);
> > > > + break;
> > > > + case PAGE_SIZE:
> > > > + out = 0 | (1 << 2);
> > > > + break;
> > > > + default:
> > > > + /*
> > > > + * Only support mapping at the page level granulatity when
> > > > + * it's an unusual length. This should get us back onto a larger
> > > > + * block size for the subsequent mappings.
> > > > + */
> > > > + out = 0 | ((MIN(size >> PAGE_SHIFT, PTRS_PER_PTE - 1)) << 2);
> > > > + break;
> > > > + }
> > > > +
> > > > + WARN_ON(phys & ~PAGE_MASK);
> > > > +
> > > > + out |= phys & PAGE_MASK;
> > > > +
> > > > + return out;
> > > > +}
> > > > +
> > > > +int realm_map_protected(struct kvm *kvm,
> > > > + unsigned long ipa,
> > > > + kvm_pfn_t pfn,
> > > > + unsigned long map_size,
> > > > + struct kvm_mmu_memory_cache *memcache)
> > > > +{
> > > > + struct realm *realm = &kvm->arch.realm;
> > > > + phys_addr_t phys = __pfn_to_phys(pfn);
> > > > + phys_addr_t base_phys = phys;
> > > > + phys_addr_t rd = virt_to_phys(realm->rd);
> > > > + unsigned long base_ipa = ipa;
> > > > + unsigned long ipa_top = ipa + map_size;
> > > > + int ret = 0;
> > > > +
> > > > + if (WARN_ON(!IS_ALIGNED(map_size, PAGE_SIZE) ||
> > > > + !IS_ALIGNED(ipa, map_size)))
> > > > + return -EINVAL;
> > > > +
> > > > + if (rmi_delegate_range(phys, map_size)) {
> > > > + /*
> > > > + * It's likely we raced with another VCPU on the same
> > > > + * fault. Assume the other VCPU has handled the fault
> > > > + * and return to the guest.
> > > > + */
> > > > + return 0;
> > > > + }
> > > > +
> > > > + while (ipa < ipa_top) {
> > > > + unsigned long flags = RMI_ADDR_TYPE_SINGLE;
> > > > + unsigned long range_desc = addr_range_desc(phys, ipa_top - ipa);
> > > > + unsigned long out_top;
> > > > +
> > > > + ret = rmi_rtt_data_map(rd, ipa, ipa_top, flags, range_desc,
> > > > + &out_top);
> > > > +
> > > > + if (RMI_RETURN_STATUS(ret) == RMI_ERROR_RTT) {
> > > > + /* Create missing RTTs and retry */
> > > > + int level = RMI_RETURN_INDEX(ret);
> > > > +
> > > > + WARN_ON(level == KVM_PGTABLE_LAST_LEVEL);
> > > > + ret = realm_create_rtt_levels(realm, ipa, level,
> > > > + KVM_PGTABLE_LAST_LEVEL,
> > > > + memcache);
> > > > + if (ret)
> > > > + goto err_undelegate;
> > > > +
> > > > + ret = rmi_rtt_data_map(rd, ipa, ipa_top, flags,
> > > > + range_desc, &out_top);
> > > > + }
> > > > +
> > > > + if (WARN_ON(ret))
> > > > + goto err_undelegate;
> > > > +
> > > > + phys += out_top - ipa;
> > > > + ipa = out_top;
> > > > + }
> > > > +
> > > > + return 0;
> > > > +
> > > > +err_undelegate:
> > > > + realm_unmap_private_range(kvm, base_ipa, ipa, true);
> > > > + if (WARN_ON(rmi_undelegate_range(base_phys, map_size))) {
> > > > + /* Page can't be returned to NS world so is lost */
> > > > + get_page(phys_to_page(base_phys));
> > > > + }
> > > > + return -ENXIO;
> > > > +}
> > > > +
> > > > +int realm_map_non_secure(struct realm *realm,
> > > > + unsigned long ipa,
> > > > + kvm_pfn_t pfn,
> > > > + unsigned long size,
> > > > + enum kvm_pgtable_prot prot,
> > > > + struct kvm_mmu_memory_cache *memcache)
> > > > +{
> > > > + unsigned long attr, flags = 0;
> > > > + phys_addr_t rd = virt_to_phys(realm->rd);
> > > > + phys_addr_t phys = __pfn_to_phys(pfn);
> > > > + unsigned long ipa_top = ipa + size;
> > > > + int ret;
> > > > +
> > > > + if (WARN_ON(!IS_ALIGNED(size, PAGE_SIZE) ||
> > > > + !IS_ALIGNED(ipa, size)))
> > > > + return -EINVAL;
> > > > +
> > > > + switch (prot & (KVM_PGTABLE_PROT_DEVICE | KVM_PGTABLE_PROT_NORMAL_NC)) {
> > > > + case KVM_PGTABLE_PROT_DEVICE | KVM_PGTABLE_PROT_NORMAL_NC:
> > > > + return -EINVAL;
> > > > + case KVM_PGTABLE_PROT_DEVICE:
> > > > + attr = MT_S2_FWB_DEVICE_nGnRE;
> > > > + break;
> > > > + case KVM_PGTABLE_PROT_NORMAL_NC:
> > > > + attr = MT_S2_FWB_NORMAL_NC;
> > > > + break;
> > > > + default:
> > > > + attr = MT_S2_FWB_NORMAL;
> > > > + }
> > > > +
> > > > + flags |= FIELD_PREP(RMI_RTT_UNPROT_MAP_FLAGS_MEMATTR, attr);
> > > > +
> > > > + if (prot & KVM_PGTABLE_PROT_R)
> > > > + flags |= FIELD_PREP(RMI_RTT_UNPROT_MAP_FLAGS_S2AP, RMI_S2AP_DIRECT_READ);
> > > > + if (prot & KVM_PGTABLE_PROT_W)
> > > > + flags |= FIELD_PREP(RMI_RTT_UNPROT_MAP_FLAGS_S2AP, RMI_S2AP_DIRECT_WRITE);
> > > > +
> > > > + flags |= RMI_ADDR_TYPE_SINGLE;
> > > > +
> > > > + while (ipa < ipa_top) {
> > > > + unsigned long range_desc = addr_range_desc(phys, ipa_top - ipa);
> > > > + unsigned long out_top;
> > > > +
> > > > + ret = rmi_rtt_unprot_map(rd, ipa, ipa_top, flags, range_desc,
> > > > + &out_top);
> > > > +
> > > > + if (RMI_RETURN_STATUS(ret) == RMI_ERROR_RTT) {
> > > > + /* Create missing RTTs and retry */
> > > > + int level = RMI_RETURN_INDEX(ret);
> > > > +
> > > > + WARN_ON(level == KVM_PGTABLE_LAST_LEVEL);
> > > > + ret = realm_create_rtt_levels(realm, ipa, level,
> > > > + KVM_PGTABLE_LAST_LEVEL,
> > > > + memcache);
> > > > + if (ret)
> > > > + return ret;
> > > > +
> > > > + ret = rmi_rtt_unprot_map(rd, ipa, ipa_top, flags,
> > > > + range_desc, &out_top);
> > > > + }
> > > > +
> > > > + if (WARN_ON(ret))
> > > > + return ret;
> > > > +
> > > > + phys += out_top - ipa;
> > > > + ipa = out_top;
> > > > + }
> > > > +
> > > > + return 0;
> > > > +}
> > > > +
> > > > static int populate_region_cb(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn,
> > > > struct page *src_page, void *opaque)
> > > > {
> > >
> > > Thanks,
> > > Gavin
> > >
> >
>
^ permalink raw reply
* Re: [PATCH v1] arm64: errata: Workaround NVIDIA Olympus device store/load ordering erratum
From: Shanker Donthineni @ 2026-06-05 14:34 UTC (permalink / raw)
To: Vladimir Murzin, Catalin Marinas, Will Deacon, linux-arm-kernel
Cc: Mark Rutland, linux-kernel, linux-doc, Vikram Sethi,
Jason Sequeira
In-Reply-To: <fd729256-07e8-46eb-8473-74ae6ec3a07e@arm.com>
Hi Vladimir Murzin,
On 6/5/2026 4:26 AM, Vladimir Murzin wrote:
> External email: Use caution opening links or attachments
>
>
> On 6/5/26 00:12, Shanker Donthineni wrote:
>> On systems with NVIDIA Olympus cores, a Device-nGnR* load can be
>> observed by a peripheral before an older, non-overlapping Device-nGnR*
>> store to the same peripheral. This breaks the program-order guarantee
>> that software expects for Device-nGnR* accesses and can leave a
>> peripheral in an incorrect state, as a load is observed before an
>> earlier store takes effect.
>>
>> The erratum can occur only when all of the following apply:
>>
>> - A PE executes a Device-nGnR* store followed by a younger
>> Device-nGnR* load.
>> - The store is not a store-release.
>> - The accesses target the same peripheral and do not overlap in bytes.
>> - There is at most one intervening Device-nGnR* store in program
>> order, and there are no intervening Device-nGnR* loads.
>> - There is no DSB, and no DMB that orders loads, between the store and
>> the load.
>> - Specific micro-architectural and timing conditions occur.
>>
>> Two ways to restore ordering: insert a barrier (any DSB, or a DMB that
>> orders loads) between the store and the load, or make the store a
>> store-release. A load-acquire on the load side would not help, because
>> acquire semantics do not prevent a load from being observed ahead of an
>> older store; only the store side (release or a barrier) closes the
>> window.
>>
>> Promote the raw MMIO store helpers (__raw_writeb/w/l/q) from plain str*
>> to stlr* (Store-Release), which removes the "store is not a
>> store-release" condition for every device write the kernel issues.
>> Because writel() and writel_relaxed() are both built on __raw_writel()
>> in asm-generic/io.h, patching the raw variants covers both the
>> non-relaxed and relaxed APIs without touching the higher layers. Note
>> that writel()'s own barrier sits before the store, so it does not order
>> the store against a subsequent readl(); the store-release promotion is
>> what provides that ordering.
>>
>> Like ARM64_ERRATUM_832075 on the load side, the change is gated on a new
>> ARM64_WORKAROUND_DEVICE_STORE_RELEASE capability and only activated on
>> parts that match MIDR_NVIDIA_OLYMPUS, so unaffected CPUs continue to use
>> the plain str* sequence.
>>
>> Co-developed-by: Vikram Sethi <vsethi@nvidia.com>
>> Signed-off-by: Vikram Sethi <vsethi@nvidia.com>
>> Signed-off-by: Shanker Donthineni <sdonthineni@nvidia.com>
>> ---
>> Documentation/arch/arm64/silicon-errata.rst | 2 ++
>> arch/arm64/Kconfig | 23 ++++++++++++++++++++
>> arch/arm64/include/asm/io.h | 24 ++++++++++++++-------
>> arch/arm64/kernel/cpu_errata.c | 8 +++++++
>> arch/arm64/tools/cpucaps | 1 +
>> 5 files changed, 50 insertions(+), 8 deletions(-)
>>
>> diff --git a/Documentation/arch/arm64/silicon-errata.rst b/Documentation/arch/arm64/silicon-errata.rst
>> index 211119ce7adc..899bed3908bb 100644
>> --- a/Documentation/arch/arm64/silicon-errata.rst
>> +++ b/Documentation/arch/arm64/silicon-errata.rst
>> @@ -256,6 +256,8 @@ stable kernels.
>> +----------------+-----------------+-----------------+-----------------------------+
>> | NVIDIA | Carmel Core | N/A | NVIDIA_CARMEL_CNP_ERRATUM |
>> +----------------+-----------------+-----------------+-----------------------------+
>> +| NVIDIA | Olympus core | T410-OLY-1027 | NVIDIA_OLYMPUS_1027_ERRATUM |
>> ++----------------+-----------------+-----------------+-----------------------------+
>> | NVIDIA | T241 GICv3/4.x | T241-FABRIC-4 | N/A |
>> +----------------+-----------------+-----------------+-----------------------------+
>> | NVIDIA | T241 MPAM | T241-MPAM-1 | N/A |
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index fe60738e5943..a6bac84b05a1 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -564,6 +564,29 @@ config ARM64_ERRATUM_832075
>>
>> If unsure, say Y.
>>
>> +config NVIDIA_OLYMPUS_1027_ERRATUM
>> + bool "NVIDIA Olympus: device store/load ordering erratum"
>> + default y
>> + help
>> + This option adds an alternative code sequence to work around an
>> + NVIDIA Olympus core erratum where a Device-nGnR* store can be
>> + observed by a peripheral after a younger Device-nGnR* load to the
>> + same peripheral. This breaks the program order that drivers rely
>> + on for MMIO and can leave a device in an incorrect state.
>> +
>> + The workaround promotes the raw MMIO store helpers
>> + (__raw_writeb/w/l/q) to Store-Release (STLR), which restores the
>> + required ordering. Because writel() and writel_relaxed() are built
>> + on __raw_writel(), both are covered without changes to the higher
>> + layers.
>> +
>> + The fix is applied through the alternatives framework, so enabling
>> + this option does not by itself activate the workaround: it is
>> + patched in only when an affected CPU is detected, and is a no-op on
>> + unaffected CPUs.
>> +
>> + If unsure, say Y.
>> +
>> config ARM64_ERRATUM_834220
>> bool "Cortex-A57: 834220: Stage 2 translation fault might be incorrectly reported in presence of a Stage 1 fault (rare)"
>> depends on KVM
>> diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
>> index 8cbd1e96fd50..b6d7966e9c19 100644
>> --- a/arch/arm64/include/asm/io.h
>> +++ b/arch/arm64/include/asm/io.h
>> @@ -25,29 +25,37 @@
>> #define __raw_writeb __raw_writeb
>> static __always_inline void __raw_writeb(u8 val, volatile void __iomem *addr)
>> {
>> - volatile u8 __iomem *ptr = addr;
>> - asm volatile("strb %w0, %1" : : "rZ" (val), "Qo" (*ptr));
>> + asm volatile(ALTERNATIVE("strb %w0, [%1]",
>> + "stlrb %w0, [%1]",
>> + ARM64_WORKAROUND_DEVICE_STORE_RELEASE)
>> + : : "rZ" (val), "r" (addr));
>> }
>>
> Nitpick:
>
> The change has the side effect of undoing d044d6ba6f02 ("arm64:
> io: permit offset addressing"), since stlr* do not support
> offset addressing. Unaffected CPUs would continue to use str*,
> but would lose the benefit of offset addressing :(
>
> Not sure if this needs to be mentioned in the commit message...
>
Thanks for your feedback, You're right that this reverts the
offset-addressing benefit of d044d6ba6f02 for the str* path too, because
stlr* has no offset form and both alternates must share one compile-time
operand form (alternatives are patched at boot). Keeping offset
addressing only for the unaffected str* path would need a runtime branch
per str operation, which isn't worth it for this optimization. I'll call
this out explicitly in the commit message in the v2 patch. -Shanker
^ permalink raw reply
* Re: [PATCH v01] mailbox/pcc.c: add query channel function
From: Adam Young @ 2026-06-05 14:19 UTC (permalink / raw)
To: Sudeep Holla, Adam Young
Cc: Jassi Brar, Rafael J. Wysocki, Saket Dumbre, Len Brown,
linux-kernel, linux-hwmon, linux-acpi, Andi Shyti, Guenter Roeck,
Huisong Li, MyungJoo Ham, Kyungmin Park, Chanwoo Choi,
linux-arm-kernel
In-Reply-To: <20260605-undetectable-polecat-of-wonder-f817c0@sudeepholla>
MCTP-PCC. I was not sure if I should ad the Patch to this one or not,
as the MCTP-PCC is still going through review.
Essentially, it need two pieces of information before start up. 1, it
needs to be able to check the sizes of the two shared memory buffers in
order to set the MTU. 2, it confirms that the Channels are indeed Type3
and Type4.
The base patch for that is
https://lore.kernel.org/lkml/20260522193610.234166-1-admiyo@os.amperecomputing.com/
This is the diff that would use them.
commit c02159450cf38cb778105f10a11708d358a3b633
(admiyo/mctp-pcc-v45-net-next, mctp-pcc-v45-net-next)
Author: Adam Young <admiyo@os.amperecomputing.com>
Date: Thu Apr 30 10:48:41 2026 -0700
mctp-pcc query channel information without opening channel.
Opening the channel can trigger the sending of
a message from the remote side before the driver
is ready to read it. Take advantage of the API that allows
querying of the channel data without opening the channel.
diff --git a/drivers/net/mctp/mctp-pcc.c b/drivers/net/mctp/mctp-pcc.c
index bb5d53ee3d7c..01a9966eddd2 100644
--- a/drivers/net/mctp/mctp-pcc.c
+++ b/drivers/net/mctp/mctp-pcc.c
@@ -318,25 +318,50 @@ static void mctp_cleanup_netdev(void *data)
mctp_unregister_netdev(ndev);
}
+static int check_channel_types(struct mctp_pcc_ndev *mctp_pcc_ndev)
+{
+ struct mctp_pcc_mailbox *outbox;
+ struct mctp_pcc_mailbox *inbox;
+ struct pcc_mbox_chan chan;
+ int actual_type;
+
+ outbox = &mctp_pcc_ndev->outbox;
+ if (pcc_mbox_query_channel(&chan, outbox->index))
+ return -EINVAL;
+ actual_type = chan.type;
+ if (actual_type != ACPI_PCCT_TYPE_EXT_PCC_MASTER_SUBSPACE){
+ pr_err("MCTP-PCC outbox channel wrong type:
%d",actual_type);
+ return -EINVAL;
+ }
+
+ inbox = &mctp_pcc_ndev->inbox;
+ if (pcc_mbox_query_channel(&chan, inbox->index))
+ return -EINVAL;
+ actual_type = chan.type;
+ if (actual_type != ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE){
+ pr_err("MCTP-PCC inbox channel wrong type: %d",actual_type);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int initialize_mtu(struct net_device *ndev)
{
struct mctp_pcc_ndev *mctp_pcc_ndev;
struct mctp_pcc_mailbox *outbox;
struct pcc_mbox_chan *pchan;
+ struct pcc_mbox_chan chan;
int mctp_pcc_max_mtu;
mctp_pcc_ndev = netdev_priv(ndev);
outbox = &mctp_pcc_ndev->outbox;
- pchan = pcc_mbox_request_channel(&outbox->client, outbox->index);
- if (IS_ERR(pchan))
- return PTR_ERR(pchan);
- if (pchan->shmem_size < MCTP_MIN_MTU + sizeof(struct
acpi_pcct_ext_pcc_shared_memory)) {
- pcc_mbox_free_channel(pchan);
+ if (pcc_mbox_query_channel(&chan, outbox->index))
+ return -EINVAL;
+ if (chan.shmem_size < MCTP_MIN_MTU + sizeof(struct
acpi_pcct_ext_pcc_shared_memory)) {
return -EINVAL;
}
- mctp_pcc_max_mtu = pchan->shmem_size - sizeof(struct
acpi_pcct_ext_pcc_shared_memory);
- pcc_mbox_free_channel(pchan);
-
+ mctp_pcc_max_mtu = chan.shmem_size - sizeof(struct
acpi_pcct_ext_pcc_shared_memory);
ndev->mtu = MCTP_MIN_MTU;
ndev->max_mtu = mctp_pcc_max_mtu;
ndev->min_mtu = MCTP_MIN_MTU;
@@ -378,7 +403,6 @@ static int mctp_pcc_driver_add(struct acpi_device
*acpi_dev)
return -ENOMEM;
mctp_pcc_ndev = netdev_priv(ndev);
-
mctp_pcc_ndev->inbox.index = context.inbox_index;
mctp_pcc_ndev->inbox.client.dev = dev;
mctp_pcc_ndev->outbox.index = context.outbox_index;
On 6/5/26 03:55, Sudeep Holla wrote:
> On Thu, Jun 04, 2026 at 04:37:48PM -0400, Adam Young wrote:
>> Drivers need information about a channel prior to creating a channel
>> or they risk triggering message delivery on the remote side of a
>> connection.
>>
>> One of those pieces of infomration is the type of channel.
>>
>> Add PCC channel type to records and expose PCC channel type to client.
>>
> Please point me to the user of this interface.
>
^ permalink raw reply related
* Re: [PATCH v3 3/3] iommu/arm-smmu-v3: Issue CFGI/TLBI twice on Tegra264
From: Ashish Mhetre @ 2026-06-05 14:12 UTC (permalink / raw)
To: Will Deacon
Cc: robin.murphy, joro, jgg, nicolinc, linux-arm-kernel, iommu,
linux-kernel, linux-tegra
In-Reply-To: <ah87dzHOOTNGBBmt@willie-the-truck>
On 6/3/2026 1:52 AM, Will Deacon wrote:
> External email: Use caution opening links or attachments
>
>
> On Mon, Jun 01, 2026 at 10:48:45AM +0000, Ashish Mhetre wrote:
>> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
>> index 1e9f7d2de344..78c96a2b652b 100644
>> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
>> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
>> @@ -350,6 +350,26 @@ static int arm_vsmmu_convert_user_cmd(struct arm_vsmmu *vsmmu,
>> return 0;
>> }
>>
>> +/*
>> + * On Tegra264, arm_smmu_cmdq_issue_cmdlist() doubles every CFGI/TLBI
>> + * submission (see ARM_SMMU_OPT_TLBI_TWICE). The doubling decision is
>> + * taken once per cmdlist based on the first command, so a single
>> + * batch must not mix commands that need doubling with commands that
>> + * do not. Split the iommufd batch whenever the next user command
>> + * crosses that boundary.
>> + */
> Again, I wouldn't bother with this comment. You probably _should_ update
> Documentation/arch/arm64/silicon-errata.rst, however.
Ack, I'll remove this comment and add in Documentation.
>> +static bool arm_vsmmu_can_batch_cmd(struct arm_smmu_device *smmu,
>> + struct arm_vsmmu_invalidation_cmd *last,
>> + struct arm_vsmmu_invalidation_cmd *next)
>> +{
>> + struct arm_smmu_cmd next_cmd = {
>> + .data[0] = le64_to_cpu(next->ucmd.cmd[0]),
>> + };
>> +
>> + return arm_smmu_cmd_needs_tlbi_twice(smmu, &last->cmd) ==
>> + arm_smmu_cmd_needs_tlbi_twice(smmu, &next_cmd);
>> +}
>> +
>> int arm_vsmmu_cache_invalidate(struct iommufd_viommu *viommu,
>> struct iommu_user_data_array *array)
>> {
>> @@ -382,7 +402,8 @@ int arm_vsmmu_cache_invalidate(struct iommufd_viommu *viommu,
>>
>> /* FIXME work in blocks of CMDQ_BATCH_ENTRIES and copy each block? */
>> cur++;
>> - if (cur != end && (cur - last) != CMDQ_BATCH_ENTRIES - 1)
>> + if (cur != end && (cur - last) != CMDQ_BATCH_ENTRIES - 1 &&
>> + arm_vsmmu_can_batch_cmd(smmu, last, cur))
>> continue;
> FYI: Sashiko is unhappy with the existing code here, so somebody should
> check that out:
>
> https://sashiko.dev/#/patchset/20260601104845.995005-2-amhetre@nvidia.com
>
>> /* FIXME always uses the main cmdq rather than trying to group by type */
>> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
>> index 08684bd40a6d..f38c21b56f28 100644
>> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
>> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
>> @@ -698,10 +698,10 @@ static void arm_smmu_cmdq_write_entries(struct arm_smmu_cmdq *cmdq,
>> * insert their own list of commands then all of the commands from one
>> * CPU will appear before any of the commands from the other CPU.
>> */
>> -int arm_smmu_cmdq_issue_cmdlist(struct arm_smmu_device *smmu,
>> - struct arm_smmu_cmdq *cmdq,
>> - struct arm_smmu_cmd *cmds, int n,
>> - bool sync)
>> +static int __arm_smmu_cmdq_issue_cmdlist(struct arm_smmu_device *smmu,
>> + struct arm_smmu_cmdq *cmdq,
>> + struct arm_smmu_cmd *cmds, int n,
>> + bool sync)
>> {
>> struct arm_smmu_cmd cmd_sync;
>> u32 prod;
>> @@ -820,6 +820,26 @@ int arm_smmu_cmdq_issue_cmdlist(struct arm_smmu_device *smmu,
>> return ret;
>> }
>>
>> +int arm_smmu_cmdq_issue_cmdlist(struct arm_smmu_device *smmu,
>> + struct arm_smmu_cmdq *cmdq,
>> + struct arm_smmu_cmd *cmds, int n,
>> + bool sync)
>> +{
>> + int ret = __arm_smmu_cmdq_issue_cmdlist(smmu, cmdq, cmds, n, sync);
>> +
>> + /*
>> + * On Tegra264 (see ARM_SMMU_OPT_TLBI_TWICE) re-issue the same
>> + * cmdlist with another CMD_SYNC to satisfy the erratum.
>> + * Callers must ensure the batch carries a uniform opcode class
>> + * so that checking the first command is enough; the iommufd
>> + * VSMMU path enforces this with arm_vsmmu_can_batch_cmd().
>> + */
>> + if (!ret && sync && arm_smmu_cmd_needs_tlbi_twice(smmu, &cmds[0]))
> Can you move the arm_smmu_cmd_... part to the start of the conjunction,
> please? If you make it a static key as I mentioned previously, then
> hopefully that should mean everything else is moved out of line.
Okay, I'll fix this in V4.
>> + ret = __arm_smmu_cmdq_issue_cmdlist(smmu, cmdq, cmds, n, sync);
> Sashiko is also unhappy here if n == 0 because we probably shouldn't
> be inspecting the command array in that case. Generally, it's a pity
> that we can't handle this all a bit further up in the stack when we know
> exactly what operationg we're trying to perform, but I suppose with all
> the different users of the invalidation commands that's hard to catch in
> one place?
>
>> +
>> + return ret;
>> +}
>> +
>> static int arm_smmu_cmdq_issue_cmd_p(struct arm_smmu_device *smmu,
>> struct arm_smmu_cmd *cmd, bool sync)
>> {
>> @@ -863,6 +883,14 @@ static bool arm_smmu_cmdq_batch_force_sync(struct arm_smmu_device *smmu,
>> (smmu->options & ARM_SMMU_OPT_CMDQ_FORCE_SYNC))
>> return true;
>>
>> + /*
>> + * Tegra264 erratum (see ARM_SMMU_OPT_TLBI_TWICE). The batch holds
>> + * a uniform opcode class, so checking the first command is enough.
>> + */
> Again, please drop the Tegra264 mention and just refer to the option.
Ack.
> Will
^ permalink raw reply
* Re: [PATCH v3 2/3] iommu/arm-smmu-v3: Detect Tegra264 erratum
From: Jason Gunthorpe @ 2026-06-05 14:10 UTC (permalink / raw)
To: Ashish Mhetre
Cc: Will Deacon, robin.murphy, joro, nicolinc, linux-arm-kernel,
iommu, linux-kernel, linux-tegra
In-Reply-To: <09a501ff-d1e8-4035-95c1-a6df9f0cb9d0@nvidia.com>
On Fri, Jun 05, 2026 at 07:35:35PM +0530, Ashish Mhetre wrote:
> > > +{
> > > + if (!(smmu->options & ARM_SMMU_OPT_TLBI_TWICE))
> > > + return false;
> > Maybe we should make this a static key?
>
> Okay. Shall I add just static key and remove option bit, or
> have static key alongside existing option bit such that
> static_branch_unlikely will precede the option bit check?
You'd have the static key and the options. Keep it simple, enable the
static key once if any driver probes to set TWICE. Check the key
before options to get the best code gen
But IDK if it is really worth it, there are already lots of branches
on the performance tlbi flow, and we didn't do this for other tlbi
affecting errata..
IDK if we really care about branches we should also be doing things
like disabling the range/non-range paths and ATC based on what is
actually in use..
Jason
^ permalink raw reply
* Re: [PATCH v3 2/3] iommu/arm-smmu-v3: Detect Tegra264 erratum
From: Ashish Mhetre @ 2026-06-05 14:05 UTC (permalink / raw)
To: Will Deacon
Cc: robin.murphy, joro, jgg, nicolinc, linux-arm-kernel, iommu,
linux-kernel, linux-tegra
In-Reply-To: <ah85c4u011WNJQgE@willie-the-truck>
On 6/3/2026 1:43 AM, Will Deacon wrote:
> External email: Use caution opening links or attachments
>
>
> On Mon, Jun 01, 2026 at 10:48:44AM +0000, Ashish Mhetre wrote:
>> Tegra264 SMMU is affected by erratum where a TLB entry can survive an
>> invalidation that races with concurrent traffic targeting the same
>> entry. The hardware-recommended software workaround is to issue every
>> CFGI/TLBI command (each followed by CMD_SYNC) twice. The second issue
>> is guaranteed to evict the entry. ATC_INV is not affected and must not
>> be doubled.
>>
>> The erratum is not flagged by any SMMUv3 IDR/IIDR register, so it
>> cannot be detected from hardware ID. Tegra264 boots from device tree
>> only and has no ACPI/IORT support, so detection is through device
>> tree only.
> That seems odd to me -- whether the hardware has the erratum is
> completely unrelated to whether it probes using DT or ACPI, so I find it
> really weird to have the workaround enabled when booting with DT and not
> when booting with ACPI. We should have consistent behaviour between the
> two.
>
>> Add the ARM_SMMU_OPT_TLBI_TWICE option and set it on instances matching
>> the existing "nvidia,tegra264-smmu" compatible. Also add a
>> static-inline arm_smmu_cmd_needs_tlbi_twice() classifier in
>> arm-smmu-v3.h so that subsequent changes wiring the workaround into the
>> CMDQ submission and iommufd batching paths can share a single
>> predicate.
>>
>> No callers consume the option yet; a subsequent change will wire the
>> workaround into the CMDQ issue paths.
>>
>> Signed-off-by: Ashish Mhetre <amhetre@nvidia.com>
>> Reviewed-by: Nicolin Chen <nicolinc@nvidia.com>
>> ---
>> drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 4 ++-
>> drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 40 +++++++++++++++++++++
>> 2 files changed, 43 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
>> index 4d29bd343460..08684bd40a6d 100644
>> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
>> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
>> @@ -5243,8 +5243,10 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev,
>> if (of_dma_is_coherent(dev->of_node))
>> smmu->features |= ARM_SMMU_FEAT_COHERENCY;
>>
>> - if (of_device_is_compatible(dev->of_node, "nvidia,tegra264-smmu"))
>> + if (of_device_is_compatible(dev->of_node, "nvidia,tegra264-smmu")) {
>> tegra_cmdqv_dt_probe(dev->of_node, smmu);
>> + smmu->options |= ARM_SMMU_OPT_TLBI_TWICE;
>> + }
>>
>> return ret;
>> }
>> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
>> index 16353596e08a..106034c348a1 100644
>> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
>> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
>> @@ -928,6 +928,14 @@ struct arm_smmu_device {
>> #define ARM_SMMU_OPT_MSIPOLL (1 << 2)
>> #define ARM_SMMU_OPT_CMDQ_FORCE_SYNC (1 << 3)
>> #define ARM_SMMU_OPT_TEGRA241_CMDQV (1 << 4)
>> +/*
>> + * Tegra264 erratum: a TLB entry can survive an invalidation that races
>> + * with concurrent traffic targeting the same entry. The software
>> + * workaround is to issue every CFGI/TLBI command twice, each followed
>> + * by CMD_SYNC. The second issue is guaranteed to evict the entry.
>> + * ATC_INV commands are not affected and must not be doubled.
>> + */
>> +#define ARM_SMMU_OPT_TLBI_TWICE (1 << 5)
> nit: I think this should be named slightly differently as it covers CFGI
> as well. Maybe ARM_SMMU_OPT_REPEAT_TLBI_CFGI ?
>
> The comment can be simpler too and avoid being specific to Tegra264. The
> main things to say are that it repeats {CFGI,TLBI}; SYNC sequences and
> does not apply to ATC_INV.
Ack, I will fix this in V4.
>> +/*
>> + * Returns true if @cmd is one of the CFGI_* or TLBI_* commands covered
>> + * by the Tegra264 erratum (see ARM_SMMU_OPT_TLBI_TWICE) on an affected
>> + * SMMU instance.
>> + */
> (remove the comment)
Ack.
>> +static inline bool arm_smmu_cmd_needs_tlbi_twice(struct arm_smmu_device *smmu,
>> + struct arm_smmu_cmd *cmd)
> Rename the function to something like arm_smmu_erratum_cmd_needs_repeating()?
Ack.
>> +{
>> + if (!(smmu->options & ARM_SMMU_OPT_TLBI_TWICE))
>> + return false;
> Maybe we should make this a static key?
Okay. Shall I add just static key and remove option bit, or
have static key alongside existing option bit such that
static_branch_unlikely will precede the option bit check?
>> + switch (FIELD_GET(CMDQ_0_OP, cmd->data[0])) {
>> + case CMDQ_OP_CFGI_STE:
>> + case CMDQ_OP_CFGI_ALL:
>> + case CMDQ_OP_CFGI_CD:
>> + case CMDQ_OP_CFGI_CD_ALL:
>> + case CMDQ_OP_TLBI_NH_ALL:
>> + case CMDQ_OP_TLBI_NH_ASID:
>> + case CMDQ_OP_TLBI_NH_VA:
>> + case CMDQ_OP_TLBI_NH_VAA:
>> + case CMDQ_OP_TLBI_EL2_ALL:
>> + case CMDQ_OP_TLBI_EL2_ASID:
>> + case CMDQ_OP_TLBI_EL2_VA:
>> + case CMDQ_OP_TLBI_S12_VMALL:
>> + case CMDQ_OP_TLBI_S2_IPA:
>> + case CMDQ_OP_TLBI_NSNH_ALL:
>> + return true;
> Isn't this just everything < ATC_INV || >= CFGI_STE? Seems better than
> enumerating everything.
Ack.
> Will
Thanks,
Ashish Mhetre
^ permalink raw reply
* Re: [PATCH] net: stmmac: xgmac: report L3/L4 filter match count in ethtool stats
From: Andrew Lunn @ 2026-06-05 14:04 UTC (permalink / raw)
To: Nazle Asmade, Muhammad Nazim Amirul
Cc: netdev@vger.kernel.org, andrew+netdev@lunn.ch,
davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
pabeni@redhat.com, mcoquelin.stm32@gmail.com,
alexandre.torgue@foss.st.com, rmk+kernel@armlinux.org.uk,
maxime.chevallier@bootlin.com,
linux-stm32@st-md-mailman.stormreply.com,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org
In-Reply-To: <ed1ead6c-0505-4e56-97e3-b8e32e3e8e2b@altera.com>
> To reply on Andrew question - As per what I'm seeing, the XGMAC2 RDES2
> only defines L3FM (bit 27) and L4FM (bit 28) — there is no FILT_NB_MATCH
> equivalent in the XGMAC2 descriptor layout, unlike dwmac4 which exposes
> it via RDES2 bits [27:26]. This patch covers all filter match bits
> available in XGMAC2 RDES2.
Thanks for the information.
Andrew
^ permalink raw reply
* Re: [PATCH v4 3/4] perf/arm64: Add BRBE support for bpf_get_branch_snapshot()
From: Rob Herring @ 2026-06-05 13:53 UTC (permalink / raw)
To: Puranjay Mohan
Cc: bpf, Puranjay Mohan, Alexei Starovoitov, Daniel Borkmann,
John Fastabend, Andrii Nakryiko, Martin KaFai Lau,
Eduard Zingerman, Song Liu, Yonghong Song, Will Deacon,
Mark Rutland, Catalin Marinas, Leo Yan, Peter Zijlstra,
Ingo Molnar, Arnaldo Carvalho de Melo, Namhyung Kim, James Clark,
Ian Rogers, Adrian Hunter, Shuah Khan, Breno Leitao,
Ravi Bangoria, Stephane Eranian, Kumar Kartikeya Dwivedi,
Usama Arif, linux-arm-kernel, linux-perf-users, linux-kselftest,
linux-kernel, kernel-team
In-Reply-To: <20260527121207.2312181-4-puranjay@kernel.org>
On Wed, May 27, 2026 at 05:11:59AM -0700, Puranjay Mohan wrote:
> Enable bpf_get_branch_snapshot() on ARM64 by implementing the
> perf_snapshot_branch_stack static call for BRBE.
>
> BRBE is paused before masking exceptions to avoid branch buffer
> pollution from trace_hardirqs_off(). Exceptions are then masked with
> local_daif_save() to prevent PMU overflow pseudo-NMIs from interfering.
> If an overflow between pause and DAIF save re-enables BRBE, the snapshot
> detects this via BRBFCR_EL1.PAUSED and bails out.
>
> Branch records are read using perf_entry_from_brbe_regset() with a NULL
> event pointer to bypass event-specific filtering. The buffer is
> invalidated after reading.
>
> Introduce a for_each_brbe_entry() iterator to deduplicate bank
> iteration between brbe_read_filtered_entries() and the snapshot.
>
> Signed-off-by: Puranjay Mohan <puranjay@kernel.org>
> ---
> drivers/perf/arm_brbe.c | 127 ++++++++++++++++++++++++++++++++-------
> drivers/perf/arm_brbe.h | 9 +++
> drivers/perf/arm_pmuv3.c | 5 +-
> 3 files changed, 119 insertions(+), 22 deletions(-)
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
^ permalink raw reply
* [PATCH] media: rockchip: rga: don't change RGB quantization
From: Sven Püschel @ 2026-06-05 13:32 UTC (permalink / raw)
To: Jacob Chen, Ezequiel Garcia, Mauro Carvalho Chehab,
Heiko Stuebner, Nicolas Dufresne, Hans Verkuil
Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
kernel, Philipp Zabel, Michael Tretter, Sven Püschel
Don't change the quantization of an RGB format when converting between
RGB and YUV with the RGA3. As the RGA3 only supports doing conversions
to full range YUV with BT601, it wants to announce it through
try_fmt/s_fmt.
As it is only relevant, when converting between RGB and YUV, it's
guarded by a given condition. But the condition also causes the
RGB format quantization to be adjusted to limited range, which
is incorrect.
Therefore simplify the condition to only apply when the current format
is a YUV format. Also document the reason for checking if the other
format is an RGB format.
Fixes: 24a63d4c9d3c ("media: rockchip: rga: add rga3 support")
Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
---
This patch is a fix to the upcoming RGA3 support. By mistake it'll also
adjust the RGB quantization instead of only adjusting the quantization
of the YUV formats. Therefore remove the incorrect conditions and
document why we also check the format of the other side.
I've just noticed this flawed condition and didn't check/reproduce it in
a practical scenario.
v4l2-compliance 1.32.0, 64 bits, 64-bit time_t
....
Card type : rga3
...
Total for rockchip-rga device /dev/video0: 48, Succeeded: 48, Failed: 0, Warnings: 0
v4l2-compliance 1.32.0, 64 bits, 64-bit time_t
...
Card type : rga2
...
Total for rockchip-rga device /dev/video1: 48, Succeeded: 48, Failed: 0, Warnings: 0
---
drivers/media/platform/rockchip/rga/rga3-hw.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/drivers/media/platform/rockchip/rga/rga3-hw.c b/drivers/media/platform/rockchip/rga/rga3-hw.c
index ca1c268303dd4..c4a71306278ba 100644
--- a/drivers/media/platform/rockchip/rga/rga3-hw.c
+++ b/drivers/media/platform/rockchip/rga/rga3-hw.c
@@ -450,10 +450,14 @@ static void *rga3_adjust_and_map_format(struct rga_ctx *ctx,
other_format = is_output ? &ctx->out.pix : &ctx->in.pix;
other_format_info = v4l2_format_info(other_format->pixelformat);
- if ((v4l2_is_format_rgb(format_info) &&
- v4l2_is_format_yuv(other_format_info)) ||
- (v4l2_is_format_yuv(format_info) &&
- v4l2_is_format_rgb(other_format_info))) {
+ /*
+ * Only apply the quantization restrictions when we need to
+ * convert between RGB and YUV. Otherwise there is no point
+ * to limit the quantization for operations like scaling or
+ * rotations.
+ */
+ if (v4l2_is_format_yuv(format_info) &&
+ v4l2_is_format_rgb(other_format_info)) {
/*
* The RGA3 only supports BT601, BT709 and BT2020 RGB<->YUV conversions
* Additionally BT709 and BT2020 only support limited range YUV.
---
base-commit: 6a75e3d4f6428b90f398354212e3a2e0172851d6
change-id: 20260605-spu-fixrga3quantization-061c761a1d80
Best regards,
--
Sven Püschel <s.pueschel@pengutronix.de>
^ permalink raw reply related
* Re: [PATCH v2] EDAC/synopsys: Fix cleanup on injection sysfs failure
From: Michal Simek @ 2026-06-05 13:23 UTC (permalink / raw)
To: Yuho Choi, Borislav Petkov, Tony Luck
Cc: linux-edac, linux-arm-kernel, linux-kernel
In-Reply-To: <20260605125417.2348115-1-dbgh9129@gmail.com>
On 6/5/26 14:54, Yuho Choi wrote:
> edac_create_sysfs_attributes() creates inject_data_error before
> inject_data_poison. If the second file creation fails, the first file is
> left behind.
>
> The same failure path runs after edac_mc_add_mc() has registered the
> memory controller with the EDAC core. Jumping directly to edac_mc_free()
> skips edac_mc_del_mc() and leaves the registered controller state
> unwound incorrectly.
>
> Remove inject_data_error when inject_data_poison creation fails, and
> route the probe failure through edac_mc_del_mc() before freeing mci.
>
> Fixes: 1a81361f75d8 ("EDAC, synopsys: Add Error Injection support for ZynqMP DDR controller")
> Signed-off-by: Yuho Choi <dbgh9129@gmail.com>
> ---
> Changes in v2:
> - Remove the CONFIG_EDAC_DEBUG-guarded del_mc label.
> - Call edac_mc_del_mc() inline before jumping to free_edac_mc when
> edac_create_sysfs_attributes() fails.
>
> drivers/edac/synopsys_edac.c | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
> index 51143b3257de..9ca2a842612e 100644
> --- a/drivers/edac/synopsys_edac.c
> +++ b/drivers/edac/synopsys_edac.c
> @@ -1120,8 +1120,10 @@ static int edac_create_sysfs_attributes(struct mem_ctl_info *mci)
> if (rc < 0)
> return rc;
> rc = device_create_file(&mci->dev, &dev_attr_inject_data_poison);
> - if (rc < 0)
> + if (rc < 0) {
> + device_remove_file(&mci->dev, &dev_attr_inject_data_error);
> return rc;
> + }
> return 0;
> }
>
> @@ -1431,6 +1433,7 @@ static int mc_probe(struct platform_device *pdev)
> if (rc) {
> edac_printk(KERN_ERR, EDAC_MC,
> "Failed to create sysfs entries\n");
> + edac_mc_del_mc(&pdev->dev);
> goto free_edac_mc;
> }
> }
Cc: stable@vger.kernel.org
Acked-by: Michal Simek <michal.simek@amd.com>
Thanks,
Michal
^ permalink raw reply
* Re: [PATCH v4 0/4] arm64: Add BRBE support for bpf_get_branch_snapshot()
From: Puranjay Mohan @ 2026-06-05 13:02 UTC (permalink / raw)
To: Rob Herring
Cc: Alexei Starovoitov, Daniel Borkmann, John Fastabend,
Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman, Song Liu,
Yonghong Song, Will Deacon, Mark Rutland, Catalin Marinas,
Leo Yan, Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, James Clark, Ian Rogers, Adrian Hunter, Shuah Khan,
Breno Leitao, Ravi Bangoria, Stephane Eranian,
Kumar Kartikeya Dwivedi, Usama Arif, linux-arm-kernel,
linux-perf-users, linux-kselftest, linux-kernel, kernel-team
In-Reply-To: <20260527121207.2312181-1-puranjay@kernel.org>
Hi Rob,
Could you please have a look at this patchset when you get a chance?
Thanks,
Puranjay
On Wed, May 27, 2026 at 1:12 PM Puranjay Mohan <puranjay@kernel.org> wrote:
>
> v3: https://lore.kernel.org/all/20260413185740.3286146-1-puranjay@kernel.org/
> Changes in v4:
> - Fix leaking branch records when scheduled task has an unrelated perf event (Sashiko)
> - Update tools/include/uapi/linux/perf_event.h as well for patch 2
> - Introduce cpu_has_brbe() and use it in
> arm_brbe_snapshot_branch_stack(0 to make sure we don't run on a CPU
> without BRBE.
> - Add explicit isb() after after writing to SYS_BRBFCR_EL1.
> - Rebase on latest arm64 tree.
>
> v2: https://lore.kernel.org/all/20260318171706.2840512-1-puranjay@kernel.org/
> Changes in v3:
> - Move NULL pmu_ctx fix from arm_pmuv3.c to perf core (Leo Yan)
> - Use union to clear branch entry bitfields instead of per-field
> zeroing (Leo Yan)
> - Remove per-CPU brbe_active flag; check BRBCR_EL1 == 0 instead (Rob
> Herring)
> - Remove redundant valid_brbidr() check in snapshot path (Rob Herring)
> - Introduce for_each_brbe_entry() iterator to deduplicate bank
> iteration (Rob Herring)
> - Include perf core maintainers (Leo Yan, Rob Herring)
>
> v1: https://lore.kernel.org/all/20260313180352.3800358-1-puranjay@kernel.org/
> Changes in v2:
> - Rebased on arm64/for-next/core
> - Add per-CPU brbe_active flag to guard against UNDEFINED sysreg access
> on non-BRBE CPUs in heterogeneous big.LITTLE systems.
> - Fix pre-existing bug in perf_clear_branch_entry_bitfields() that missed
> zeroing new_type and priv bitfields, added as a separate patch with
> Fixes tags (new patch 2).
> - Use architecture-specific selftest threshold (#if defined(__aarch64__))
> instead of raising the global threshold, to preserve x86 regression
> detection.
>
> RFC: https://lore.kernel.org/all/20260102214043.1410242-1-puranjay@kernel.org/
> Changes from RFC:
> - Fix pre-existing NULL pointer dereference in armv8pmu_sched_task()
> found by Leo Yan during testing (patch 1)
> - Pause BRBE before local_daif_save() to avoid branch pollution from
> trace_hardirqs_off()
> - Use local_daif_save() to prevent pNMI race from counter overflow
> (Mark Rutland)
> - Reuse perf_entry_from_brbe_regset() instead of duplicating register
> read logic, by making it accept NULL event (Mark Rutland)
> - Invalidate BRBE after reading to maintain record contiguity for
> other consumers (Mark Rutland)
> - Adjust selftest wasted_entries threshold for ARM64 (patch 3)
> - Tested on ARM FVP with BRBE enabled
>
> This series enables the bpf_get_branch_snapshot() BPF helper on ARM64
> by implementing the perf_snapshot_branch_stack static call for ARM's
> Branch Record Buffer Extension (BRBE).
>
> bpf_get_branch_snapshot() [1] allows BPF programs to capture hardware
> branch records on-demand from any BPF tracing context. This was
> previously only available on x86 (Intel LBR) since v5.16. With BRBE
> available on ARMv9, this series closes the gap for ARM64.
>
> Usage model
> -----------
>
> The helper works in conjunction with perf events. The userspace
> component of the BPF application opens a perf event with
> PERF_SAMPLE_BRANCH_STACK on each CPU, which configures the hardware
> to continuously record branches into BRBE (on ARM64) or LBR (on x86).
> A BPF program attached to a tracepoint, kprobe, or fentry hook can
> then call bpf_get_branch_snapshot() to snapshot the branch buffer at
> any point. Without an active perf event, BRBE is not recording and
> the buffer is empty.
>
> On-demand branch snapshots from BPF are useful for diagnosing which
> specific code path was taken inside a function. Stack traces only show
> function boundaries, but branch records reveal the exact sequence of
> jumps, calls, and returns within a function -- making it possible to
> identify which specific error check triggered a failure, or which
> callback implementation was invoked through a function pointer.
>
> For example, retsnoop [2] is a BPF-based tool for non-intrusive
> mass-tracing of kernel internals. Its LBR mode (--lbr) creates per-CPU
> perf events with PERF_SAMPLE_BRANCH_STACK and then uses
> bpf_get_branch_snapshot() in its fentry/fexit BPF programs to capture
> branch records whenever a traced function returns an error.
>
> Consider debugging a bpf() syscall that returns -EINVAL when creating
> a BPF map with invalid parameters. Running retsnoop on an ARM64 FVP
> with BRBE to trace the bpf() syscall and array_map_alloc_check():
>
> $ retsnoop -e '*sys_bpf' -a 'array_map_alloc_check' --lbr=any \
> -F -k vmlinux --debug full-lbr
> $ simfail bpf-bad-map-max-entries-array # in another terminal
>
> Output of retsnoop:
>
> --- fentry BPF program (entries #63-#17) ---
>
> [#63-#59] __htab_map_lookup_elem: hash table walk with memcmp (hashtab.c)
> [#58] __htab_map_lookup_elem+0x98 -> dump_bpf_prog+0xc850 (hashtab.c:750)
> [#57-#55] ... dump_bpf_prog internal branches ...
> [#54] dump_bpf_prog+0xcab8 -> bpf_get_current_pid_tgid+0x0 (helpers.c:225)
> [#53] bpf_get_current_pid_tgid+0x1c -> dump_bpf_prog+0xcabc (helpers.c:225)
> [#52-#51] ... dump_bpf_prog -> __htab_map_lookup_elem ...
> [#50-#47] __htab_map_lookup_elem: htab_map_hash (jhash2), select_bucket
> [#46-#42] lookup_nulls_elem_raw: hash chain walk with memcmp (hashtab.c:717)
> [#41] __htab_map_lookup_elem+0x98 -> dump_bpf_prog+0xcaf8 (hashtab.c:750)
> [#40-#37] ... dump_bpf_prog -> bpf_ktime_get_ns ...
> [#36] bpf_ktime_get_ns+0x10 -> ktime_get_mono_fast_ns+0x0 (helpers.c:178)
> [#35-#32] ktime_get_mono_fast_ns: tk_clock_read -> arch_counter_get_cntpct
> [#31] ktime_get_mono_fast_ns+0x9c -> bpf_ktime_get_ns+0x14 (timekeeping.c:493)
> [#30] bpf_ktime_get_ns+0x18 -> dump_bpf_prog+0xcd50 (helpers.c:178)
> [#29-#25] ... dump_bpf_prog internal branches ...
> [#24] dump_bpf_prog+0x11b28 -> __bpf_prog_exit_recur+0x0 (trampoline.c:1190)
> [#23-#17] __bpf_prog_exit_recur: rcu_read_unlock, migrate_enable (trampoline.c:1195)
>
> --- array_map_alloc_check (entries #16-#12) ---
>
> [#16] dump_bpf_prog+0x11b38 -> array_map_alloc_check+0x8 (arraymap.c:55)
> [#15] array_map_alloc_check+0x18 -> array_map_alloc_check+0xb8 (arraymap.c:56)
> . bpf_map_attr_numa_node . bpf_map_attr_numa_node
> [#14] array_map_alloc_check+0xbc -> array_map_alloc_check+0x20 (arraymap.c:59)
> . bpf_map_attr_numa_node
> [#13] array_map_alloc_check+0x24 -> array_map_alloc_check+0x94 (arraymap.c:64)
> [#12] array_map_alloc_check+0x98 -> dump_bpf_prog+0x11b3c (arraymap.c:82)
>
> --- fexit trampoline overhead (entries #11-#00) ---
>
> [#11] dump_bpf_prog+0x11b5c -> __bpf_prog_enter_recur+0x0 (trampoline.c:1145)
> [#10-#03] __bpf_prog_enter_recur: rcu_read_lock, migrate_disable (trampoline.c:1146)
> [#02] __bpf_prog_enter_recur+0x114 -> dump_bpf_prog+0x11b60 (trampoline.c:1157)
> [#01] dump_bpf_prog+0x11b6c -> dump_bpf_prog+0xd230
> [#00] dump_bpf_prog+0xd340 -> arm_brbe_snapshot_branch_stack+0x0 (arm_brbe.c:814)
>
> el0t_64_sync+0x168
> el0t_64_sync_handler+0x98
> el0_svc+0x28
> do_el0_svc+0x4c
> invoke_syscall.constprop.0+0x54
> 373us [-EINVAL] __arm64_sys_bpf+0x8
> __sys_bpf+0x87c
> map_create+0x120
> 95us [-EINVAL] array_map_alloc_check+0x8
>
> The FVP's BRBE buffer has 64 entries (BRBE supports 8, 16, 32, or
> 64). Of these, entries #63-#17 (47) are consumed by the fentry BPF
> trampoline that ran before the function, and entries #11-#00 (12)
> are consumed by the fexit trampoline that runs after. Entry #00
> shows the very last branch recorded before BRBE is paused: the call
> into arm_brbe_snapshot_branch_stack().
>
> The 5 useful entries (#16-#12) show the exact path taken inside
> array_map_alloc_check(). Record #14 shows a jump from line 56
> (bpf_map_attr_numa_node) to line 59 (the if-condition), and #13
> shows an immediate jump from line 59 (attr->max_entries == 0) to
> line 64 (return -EINVAL), skipping lines 60-63. This pinpoints
> max_entries==0 as the cause -- a diagnosis impossible with stack
> traces alone.
>
> [1] 856c02dbce4f ("bpf: Introduce helper bpf_get_branch_snapshot")
> [2] https://github.com/anakryiko/retsnoop
>
> Puranjay Mohan (4):
> perf/core: Fix sched_task callbacks for CPU-wide branch stack events
> perf: Use a union to clear branch entry bitfields
> perf/arm64: Add BRBE support for bpf_get_branch_snapshot()
> selftests/bpf: Adjust wasted entries threshold for ARM64 BRBE
>
> drivers/perf/arm_brbe.c | 127 +++++++++++++++---
> drivers/perf/arm_brbe.h | 9 ++
> drivers/perf/arm_pmuv3.c | 5 +-
> include/linux/perf_event.h | 9 +-
> include/uapi/linux/perf_event.h | 25 ++--
> kernel/events/core.c | 17 ++-
> tools/include/uapi/linux/perf_event.h | 25 ++--
> .../bpf/prog_tests/get_branch_snapshot.c | 13 +-
> 8 files changed, 172 insertions(+), 58 deletions(-)
>
>
> base-commit: c754aa6b881ade764510b8539a6a313326501e3d
> --
> 2.53.0-Meta
>
^ permalink raw reply
* [PATCH v2] EDAC/synopsys: Fix cleanup on injection sysfs failure
From: Yuho Choi @ 2026-06-05 12:54 UTC (permalink / raw)
To: Borislav Petkov, Tony Luck, Michal Simek
Cc: linux-edac, linux-arm-kernel, linux-kernel, Yuho Choi
edac_create_sysfs_attributes() creates inject_data_error before
inject_data_poison. If the second file creation fails, the first file is
left behind.
The same failure path runs after edac_mc_add_mc() has registered the
memory controller with the EDAC core. Jumping directly to edac_mc_free()
skips edac_mc_del_mc() and leaves the registered controller state
unwound incorrectly.
Remove inject_data_error when inject_data_poison creation fails, and
route the probe failure through edac_mc_del_mc() before freeing mci.
Fixes: 1a81361f75d8 ("EDAC, synopsys: Add Error Injection support for ZynqMP DDR controller")
Signed-off-by: Yuho Choi <dbgh9129@gmail.com>
---
Changes in v2:
- Remove the CONFIG_EDAC_DEBUG-guarded del_mc label.
- Call edac_mc_del_mc() inline before jumping to free_edac_mc when
edac_create_sysfs_attributes() fails.
drivers/edac/synopsys_edac.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index 51143b3257de..9ca2a842612e 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -1120,8 +1120,10 @@ static int edac_create_sysfs_attributes(struct mem_ctl_info *mci)
if (rc < 0)
return rc;
rc = device_create_file(&mci->dev, &dev_attr_inject_data_poison);
- if (rc < 0)
+ if (rc < 0) {
+ device_remove_file(&mci->dev, &dev_attr_inject_data_error);
return rc;
+ }
return 0;
}
@@ -1431,6 +1433,7 @@ static int mc_probe(struct platform_device *pdev)
if (rc) {
edac_printk(KERN_ERR, EDAC_MC,
"Failed to create sysfs entries\n");
+ edac_mc_del_mc(&pdev->dev);
goto free_edac_mc;
}
}
--
2.43.0
^ permalink raw reply related
* Re: [PATCH RESEND v3 1/6] drm/connector: report IRQ_HPD events to drm_connector_oob_hotplug_event()
From: Heikki Krogerus @ 2026-06-05 12:51 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Greg Kroah-Hartman, Andrzej Hajda, Neil Armstrong,
Robert Foss, Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
Adrien Grassein, Jani Nikula, Rodrigo Vivi, Joonas Lahtinen,
Tvrtko Ursulin, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
Rob Clark, Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang,
Sean Paul, Marijn Suijten, Tomi Valkeinen, Bjorn Andersson,
Konrad Dybcio, Pengyu Luo, Nikita Travkin, Yongxing Mou,
dri-devel, linux-kernel, linux-usb, intel-gfx, intel-xe,
linux-amlogic, linux-arm-kernel, linux-arm-msm, freedreno
In-Reply-To: <20260513-hpd-irq-events-v3-1-086857017f16@oss.qualcomm.com>
On Wed, May 13, 2026 at 09:23:21PM +0300, Dmitry Baryshkov wrote:
> The DisplayPort standard defines a special kind of events called IRQ.
> These events are used to notify DP Source about the events on the Sink
> side. It is extremely important for DP MST handling, where the MST
> events are reported through this IRQ.
>
> In case of the USB-C DP AltMode there is no actual HPD pulse, but the
> events are ported through the bits in the AltMode VDOs.
>
> Extend the drm_connector_oob_hotplug_event() interface and report IRQ
> events to the DisplayPort Sink drivers.
>
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
The displayport altmode looks okay to me. FWIW:
Acked-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> ---
> drivers/gpu/drm/drm_connector.c | 5 ++++-
> drivers/usb/typec/altmodes/displayport.c | 15 +++++++++++----
> include/drm/drm_connector.h | 19 ++++++++++++++++++-
> 3 files changed, 33 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
> index 47dc53c4a738..edee9daccd51 100644
> --- a/drivers/gpu/drm/drm_connector.c
> +++ b/drivers/gpu/drm/drm_connector.c
> @@ -3510,6 +3510,8 @@ struct drm_connector *drm_connector_find_by_fwnode(struct fwnode_handle *fwnode)
> * drm_connector_oob_hotplug_event - Report out-of-band hotplug event to connector
> * @connector_fwnode: fwnode_handle to report the event on
> * @status: hot plug detect logical state
> + * @extra_status: additional information provided by the sink without changing
> + * the HPD state (or in addition to such a change).
> *
> * On some hardware a hotplug event notification may come from outside the display
> * driver / device. An example of this is some USB Type-C setups where the hardware
> @@ -3520,7 +3522,8 @@ struct drm_connector *drm_connector_find_by_fwnode(struct fwnode_handle *fwnode)
> * a drm_connector reference through calling drm_connector_find_by_fwnode().
> */
> void drm_connector_oob_hotplug_event(struct fwnode_handle *connector_fwnode,
> - enum drm_connector_status status)
> + enum drm_connector_status status,
> + enum drm_connector_status_extra extra_status)
> {
> struct drm_connector *connector;
>
> diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c
> index 35d9c3086990..7182a8e2e710 100644
> --- a/drivers/usb/typec/altmodes/displayport.c
> +++ b/drivers/usb/typec/altmodes/displayport.c
> @@ -189,7 +189,9 @@ static int dp_altmode_status_update(struct dp_altmode *dp)
> } else {
> drm_connector_oob_hotplug_event(dp->connector_fwnode,
> hpd ? connector_status_connected :
> - connector_status_disconnected);
> + connector_status_disconnected,
> + (hpd && irq_hpd) ? DRM_CONNECTOR_DP_IRQ_HPD :
> + DRM_CONNECTOR_NO_EXTRA_STATUS);
> dp->hpd = hpd;
> sysfs_notify(&dp->alt->dev.kobj, "displayport", "hpd");
> if (hpd && irq_hpd) {
> @@ -212,7 +214,10 @@ static int dp_altmode_configured(struct dp_altmode *dp)
> */
> if (dp->pending_hpd) {
> drm_connector_oob_hotplug_event(dp->connector_fwnode,
> - connector_status_connected);
> + connector_status_connected,
> + dp->pending_irq_hpd ?
> + DRM_CONNECTOR_DP_IRQ_HPD :
> + DRM_CONNECTOR_NO_EXTRA_STATUS);
> sysfs_notify(&dp->alt->dev.kobj, "displayport", "hpd");
> dp->pending_hpd = false;
> if (dp->pending_irq_hpd) {
> @@ -397,7 +402,8 @@ static int dp_altmode_vdm(struct typec_altmode *alt,
> dp->data.conf = 0;
> if (dp->hpd) {
> drm_connector_oob_hotplug_event(dp->connector_fwnode,
> - connector_status_disconnected);
> + connector_status_disconnected,
> + DRM_CONNECTOR_NO_EXTRA_STATUS);
> dp->hpd = false;
> sysfs_notify(&dp->alt->dev.kobj, "displayport", "hpd");
> }
> @@ -827,7 +833,8 @@ void dp_altmode_remove(struct typec_altmode *alt)
>
> if (dp->connector_fwnode) {
> drm_connector_oob_hotplug_event(dp->connector_fwnode,
> - connector_status_disconnected);
> + connector_status_disconnected,
> + DRM_CONNECTOR_NO_EXTRA_STATUS);
>
> fwnode_handle_put(dp->connector_fwnode);
> }
> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> index f83f28cae207..e05197e970d3 100644
> --- a/include/drm/drm_connector.h
> +++ b/include/drm/drm_connector.h
> @@ -91,6 +91,22 @@ enum drm_connector_status {
> connector_status_unknown = 3,
> };
>
> +/**
> + * enum drm_connector_status_extra - additional events sent by the sink /
> + * display together or in replacement of the HPD status changes.
> + */
> +enum drm_connector_status_extra {
> + /**
> + * @DRM_CONNECTOR_NO_EXTRA_STATUS: No additional status reported.
> + */
> + DRM_CONNECTOR_NO_EXTRA_STATUS,
> + /**
> + * @DRM_CONNECTOR_DP_IRQ_HPD: DisplayPort Sink has sent the
> + * IRQ_HPD (either by the HPD short pulse or via the AltMode event).
> + */
> + DRM_CONNECTOR_DP_IRQ_HPD,
> +};
> +
> /**
> * enum drm_connector_registration_state - userspace registration status for
> * a &drm_connector
> @@ -2521,7 +2537,8 @@ drm_connector_is_unregistered(struct drm_connector *connector)
> }
>
> void drm_connector_oob_hotplug_event(struct fwnode_handle *connector_fwnode,
> - enum drm_connector_status status);
> + enum drm_connector_status status,
> + enum drm_connector_status_extra extra_status);
> const char *drm_get_connector_type_name(unsigned int connector_type);
> const char *drm_get_connector_status_name(enum drm_connector_status status);
> const char *drm_get_subpixel_order_name(enum subpixel_order order);
>
> --
> 2.47.3
--
heikki
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox