Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH v7 0/2] Add support for Variscite DART-MX95 and Sonata board
From: Francesco Dolcini @ 2026-03-25 18:06 UTC (permalink / raw)
  To: Frank Li
  Cc: Francesco Dolcini, Stefano Radaelli, devicetree, linux-kernel,
	pierluigi.p, Stefano Radaelli, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, imx, linux-arm-kernel
In-Reply-To: <acP2UX6B5js_ozWm@lizhi-Precision-Tower-5810>

On Wed, Mar 25, 2026 at 10:50:57AM -0400, Frank Li wrote:
> On Wed, Mar 25, 2026 at 01:21:04PM +0100, Francesco Dolcini wrote:
> > On Tue, Mar 24, 2026 at 03:48:29PM -0400, Frank Li wrote:
> > > On Fri, Mar 13, 2026 at 02:56:03PM -0400, Frank Li wrote:
> > > > On Fri, Mar 13, 2026 at 06:47:01PM +0100, Stefano Radaelli wrote:
> > > > > This patch series adds support for the Variscite DART-MX95 system on
> > > > > module and the Sonata carrier board.
> > > > >
> > > > > The series includes:
> > > > > - Device tree bindings documentation for both SOM and carrier board
> > > > > - SOM device tree with on-module peripherals
> > > > > - Sonata carrier board device tree with board-specific features
> > > > >
> > > > > The implementation follows the standard SOM + carrier board pattern
> > > > > where the SOM dtsi contains only peripherals mounted on the module,
> > > > > while carrier-specific interfaces are enabled in the board dts.
> > > > >
> > > > > v7:
> > > > > - Order nodes in symphony dts
> > > >
> > > > Can you run https://github.com/lznuaa/dt-format for new file to easy
> > > > track and check by script later.
> > >
> > > I applied with below change
> > > - update copywrite to 2026
> >
> > How do you know that the correct copyright year is 2026?
> > The copyright years does not change to today just because it is the year
> > it was submitted.
> 
> At least it should include 2026 because it is new files in kernel
> tree.

The copyright year is not changing nor being updated just because you
are adding the file to the linux kernel tree.

Francesco




^ permalink raw reply

* Re: [PATCH v3 4/5] KVM: arm64: Enable HDBSS support and handle HDBSSF events
From: Leonardo Bras @ 2026-03-25 18:05 UTC (permalink / raw)
  To: Tian Zheng
  Cc: Leonardo Bras, maz, oupton, catalin.marinas, corbet, pbonzini,
	will, yuzenghui, wangzhou1, liuyonglong, Jonathan.Cameron,
	yezhenyu2, linuxarm, joey.gouly, kvmarm, kvm, linux-arm-kernel,
	linux-doc, linux-kernel, skhan, suzuki.poulose
In-Reply-To: <20260225040421.2683931-5-zhengtian10@huawei.com>

Hello Tian,

I am currently working on HACDBS enablement(which will be rebased on top of 
this patchset) and due to the fact HACDBS and HDBSS are kind of 
complementary I will sometimes come with some questions for issues I have 
faced myself on that part. :)

(see below)

On Wed, Feb 25, 2026 at 12:04:20PM +0800, Tian Zheng wrote:
> From: eillon <yezhenyu2@huawei.com>
> 
> HDBSS is enabled via an ioctl from userspace (e.g. QEMU) at the start of
> migration. This feature is only supported in VHE mode.
> 
> Initially, S2 PTEs doesn't contain the DBM attribute. During migration,
> write faults are handled by user_mem_abort, which relaxes permissions
> and adds the DBM bit when HDBSS is active. Once DBM is set, subsequent
> writes no longer trap, as the hardware automatically transitions the page
> from writable-clean to writable-dirty.
> 
> KVM does not scan S2 page tables to consume DBM. Instead, when HDBSS is
> enabled, the hardware observes the clean->dirty transition and records
> the corresponding page into the HDBSS buffer.
> 
> During sync_dirty_log, KVM kicks all vCPUs to force VM-Exit, ensuring
> that check_vcpu_requests flushes the HDBSS buffer and propagates the
> accumulated dirty information into the userspace-visible dirty bitmap.
> 
> Add fault handling for HDBSS including buffer full, external abort, and
> general protection fault (GPF).
> 
> Signed-off-by: eillon <yezhenyu2@huawei.com>
> Signed-off-by: Tian Zheng <zhengtian10@huawei.com>
> ---
>  arch/arm64/include/asm/esr.h      |   5 ++
>  arch/arm64/include/asm/kvm_host.h |  17 +++++
>  arch/arm64/include/asm/kvm_mmu.h  |   1 +
>  arch/arm64/include/asm/sysreg.h   |  11 ++++
>  arch/arm64/kvm/arm.c              | 102 ++++++++++++++++++++++++++++++
>  arch/arm64/kvm/hyp/vhe/switch.c   |  19 ++++++
>  arch/arm64/kvm/mmu.c              |  70 ++++++++++++++++++++
>  arch/arm64/kvm/reset.c            |   3 +
>  8 files changed, 228 insertions(+)
> 
> diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h
> index 81c17320a588..2e6b679b5908 100644
> --- a/arch/arm64/include/asm/esr.h
> +++ b/arch/arm64/include/asm/esr.h
> @@ -437,6 +437,11 @@
>  #ifndef __ASSEMBLER__
>  #include <asm/types.h>
> 
> +static inline bool esr_iss2_is_hdbssf(unsigned long esr)
> +{
> +	return ESR_ELx_ISS2(esr) & ESR_ELx_HDBSSF;
> +}
> +
>  static inline unsigned long esr_brk_comment(unsigned long esr)
>  {
>  	return esr & ESR_ELx_BRK64_ISS_COMMENT_MASK;
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index 5d5a3bbdb95e..57ee6b53e061 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -55,12 +55,17 @@
>  #define KVM_REQ_GUEST_HYP_IRQ_PENDING	KVM_ARCH_REQ(9)
>  #define KVM_REQ_MAP_L1_VNCR_EL2		KVM_ARCH_REQ(10)
>  #define KVM_REQ_VGIC_PROCESS_UPDATE	KVM_ARCH_REQ(11)
> +#define KVM_REQ_FLUSH_HDBSS			KVM_ARCH_REQ(12)
> 
>  #define KVM_DIRTY_LOG_MANUAL_CAPS   (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE | \
>  				     KVM_DIRTY_LOG_INITIALLY_SET)
> 
>  #define KVM_HAVE_MMU_RWLOCK
> 
> +/* HDBSS entry field definitions */
> +#define HDBSS_ENTRY_VALID BIT(0)
> +#define HDBSS_ENTRY_IPA GENMASK_ULL(55, 12)
> +
>  /*
>   * Mode of operation configurable with kvm-arm.mode early param.
>   * See Documentation/admin-guide/kernel-parameters.txt for more information.
> @@ -84,6 +89,7 @@ int __init kvm_arm_init_sve(void);
>  u32 __attribute_const__ kvm_target_cpu(void);
>  void kvm_reset_vcpu(struct kvm_vcpu *vcpu);
>  void kvm_arm_vcpu_destroy(struct kvm_vcpu *vcpu);
> +void kvm_arm_vcpu_free_hdbss(struct kvm_vcpu *vcpu);
> 
>  struct kvm_hyp_memcache {
>  	phys_addr_t head;
> @@ -405,6 +411,8 @@ struct kvm_arch {
>  	 * the associated pKVM instance in the hypervisor.
>  	 */
>  	struct kvm_protected_vm pkvm;
> +
> +	bool enable_hdbss;
>  };
> 
>  struct kvm_vcpu_fault_info {
> @@ -816,6 +824,12 @@ struct vcpu_reset_state {
>  	bool		reset;
>  };
> 
> +struct vcpu_hdbss_state {
> +	phys_addr_t base_phys;
> +	u32 size;
> +	u32 next_index;
> +};
> +
>  struct vncr_tlb;
> 
>  struct kvm_vcpu_arch {
> @@ -920,6 +934,9 @@ struct kvm_vcpu_arch {
> 
>  	/* Per-vcpu TLB for VNCR_EL2 -- NULL when !NV */
>  	struct vncr_tlb	*vncr_tlb;
> +
> +	/* HDBSS registers info */
> +	struct vcpu_hdbss_state hdbss;
>  };
> 
>  /*
> diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
> index d968aca0461a..3fea8cfe8869 100644
> --- a/arch/arm64/include/asm/kvm_mmu.h
> +++ b/arch/arm64/include/asm/kvm_mmu.h
> @@ -183,6 +183,7 @@ int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa,
> 
>  int kvm_handle_guest_sea(struct kvm_vcpu *vcpu);
>  int kvm_handle_guest_abort(struct kvm_vcpu *vcpu);
> +void kvm_flush_hdbss_buffer(struct kvm_vcpu *vcpu);
> 
>  phys_addr_t kvm_mmu_get_httbr(void);
>  phys_addr_t kvm_get_idmap_vector(void);
> diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
> index f4436ecc630c..d11f4d0dd4e7 100644
> --- a/arch/arm64/include/asm/sysreg.h
> +++ b/arch/arm64/include/asm/sysreg.h
> @@ -1039,6 +1039,17 @@
> 
>  #define GCS_CAP(x)	((((unsigned long)x) & GCS_CAP_ADDR_MASK) | \
>  					       GCS_CAP_VALID_TOKEN)
> +
> +/*
> + * Definitions for the HDBSS feature
> + */
> +#define HDBSS_MAX_SIZE		HDBSSBR_EL2_SZ_2MB
> +
> +#define HDBSSBR_EL2(baddr, sz)	(((baddr) & GENMASK(55, 12 + sz)) | \
> +				 FIELD_PREP(HDBSSBR_EL2_SZ_MASK, sz))
> +
> +#define HDBSSPROD_IDX(prod)	FIELD_GET(HDBSSPROD_EL2_INDEX_MASK, prod)
> +
>  /*
>   * Definitions for GICv5 instructions]
>   */
> diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> index 29f0326f7e00..d64da05e25c4 100644
> --- a/arch/arm64/kvm/arm.c
> +++ b/arch/arm64/kvm/arm.c
> @@ -125,6 +125,87 @@ int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
>  	return kvm_vcpu_exiting_guest_mode(vcpu) == IN_GUEST_MODE;
>  }
> 
> +void kvm_arm_vcpu_free_hdbss(struct kvm_vcpu *vcpu)
> +{
> +	struct page *hdbss_pg;
> +
> +	hdbss_pg = phys_to_page(vcpu->arch.hdbss.base_phys);
> +	if (hdbss_pg)
> +		__free_pages(hdbss_pg, vcpu->arch.hdbss.size);
> +
> +	vcpu->arch.hdbss.size = 0;
> +}
> +
> +static int kvm_cap_arm_enable_hdbss(struct kvm *kvm,
> +				    struct kvm_enable_cap *cap)
> +{
> +	unsigned long i;
> +	struct kvm_vcpu *vcpu;
> +	struct page *hdbss_pg = NULL;
> +	__u64 size = cap->args[0];
> +	bool enable = cap->args[1] ? true : false;
> +
> +	if (!system_supports_hdbss())
> +		return -EINVAL;
> +
> +	if (size > HDBSS_MAX_SIZE)
> +		return -EINVAL;
> +
> +	if (!enable && !kvm->arch.enable_hdbss) /* Already Off */
> +		return 0;
> +
> +	if (enable && kvm->arch.enable_hdbss) /* Already On, can't set size */
> +		return -EINVAL;
> +
> +	if (!enable) { /* Turn it off */
> +		kvm->arch.mmu.vtcr &= ~(VTCR_EL2_HD | VTCR_EL2_HDBSS | VTCR_EL2_HA);
> +
> +		kvm_for_each_vcpu(i, vcpu, kvm) {
> +			/* Kick vcpus to flush hdbss buffer. */
> +			kvm_vcpu_kick(vcpu);
> +
> +			kvm_arm_vcpu_free_hdbss(vcpu);
> +		}
> +
> +		kvm->arch.enable_hdbss = false;
> +
> +		return 0;
> +	}
> +
> +	/* Turn it on */
> +	kvm_for_each_vcpu(i, vcpu, kvm) {
> +		hdbss_pg = alloc_pages(GFP_KERNEL_ACCOUNT, size);
> +		if (!hdbss_pg)
> +			goto error_alloc;
> +
> +		vcpu->arch.hdbss = (struct vcpu_hdbss_state) {
> +			.base_phys = page_to_phys(hdbss_pg),
> +			.size = size,
> +			.next_index = 0,
> +		};
> +	}
> +
> +	kvm->arch.enable_hdbss = true;
> +	kvm->arch.mmu.vtcr |= VTCR_EL2_HD | VTCR_EL2_HDBSS | VTCR_EL2_HA;
> +
> +	/*
> +	 * We should kick vcpus out of guest mode here to load new
> +	 * vtcr value to vtcr_el2 register when re-enter guest mode.
> +	 */
> +	kvm_for_each_vcpu(i, vcpu, kvm)
> +		kvm_vcpu_kick(vcpu);
> +
> +	return 0;
> +
> +error_alloc:
> +	kvm_for_each_vcpu(i, vcpu, kvm) {
> +		if (vcpu->arch.hdbss.base_phys)
> +			kvm_arm_vcpu_free_hdbss(vcpu);
> +	}
> +
> +	return -ENOMEM;
> +}
> +
>  int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
>  			    struct kvm_enable_cap *cap)
>  {
> @@ -182,6 +263,11 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
>  		r = 0;
>  		set_bit(KVM_ARCH_FLAG_EXIT_SEA, &kvm->arch.flags);
>  		break;
> +	case KVM_CAP_ARM_HW_DIRTY_STATE_TRACK:
> +		mutex_lock(&kvm->lock);
> +		r = kvm_cap_arm_enable_hdbss(kvm, cap);
> +		mutex_unlock(&kvm->lock);
> +		break;
>  	default:
>  		break;
>  	}
> @@ -471,6 +557,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
>  			r = kvm_supports_cacheable_pfnmap();
>  		break;
> 
> +	case KVM_CAP_ARM_HW_DIRTY_STATE_TRACK:
> +		r = system_supports_hdbss();
> +		break;
>  	default:
>  		r = 0;
>  	}
> @@ -1120,6 +1209,9 @@ static int check_vcpu_requests(struct kvm_vcpu *vcpu)
>  		if (kvm_dirty_ring_check_request(vcpu))
>  			return 0;
> 
> +		if (kvm_check_request(KVM_REQ_FLUSH_HDBSS, vcpu))
> +			kvm_flush_hdbss_buffer(vcpu);
> +
>  		check_nested_vcpu_requests(vcpu);
>  	}
> 
> @@ -1898,7 +1990,17 @@ long kvm_arch_vcpu_unlocked_ioctl(struct file *filp, unsigned int ioctl,
> 
>  void kvm_arch_sync_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot)
>  {
> +	/*
> +	 * Flush all CPUs' dirty log buffers to the dirty_bitmap.  Called
> +	 * before reporting dirty_bitmap to userspace. Send a request with
> +	 * KVM_REQUEST_WAIT to flush buffer synchronously.
> +	 */
> +	struct kvm_vcpu *vcpu;
> +
> +	if (!kvm->arch.enable_hdbss)
> +		return;
> 
> +	kvm_make_all_cpus_request(kvm, KVM_REQ_FLUSH_HDBSS);
>  }
> 
>  static int kvm_vm_ioctl_set_device_addr(struct kvm *kvm,
> diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c
> index 9db3f11a4754..600cbc4f8ae9 100644
> --- a/arch/arm64/kvm/hyp/vhe/switch.c
> +++ b/arch/arm64/kvm/hyp/vhe/switch.c
> @@ -213,6 +213,23 @@ static void __vcpu_put_deactivate_traps(struct kvm_vcpu *vcpu)
>  	local_irq_restore(flags);
>  }
> 
> +static void __load_hdbss(struct kvm_vcpu *vcpu)
> +{
> +	struct kvm *kvm = vcpu->kvm;
> +	u64 br_el2, prod_el2;
> +
> +	if (!kvm->arch.enable_hdbss)
> +		return;
> +
> +	br_el2 = HDBSSBR_EL2(vcpu->arch.hdbss.base_phys, vcpu->arch.hdbss.size);
> +	prod_el2 = vcpu->arch.hdbss.next_index;
> +
> +	write_sysreg_s(br_el2, SYS_HDBSSBR_EL2);
> +	write_sysreg_s(prod_el2, SYS_HDBSSPROD_EL2);
> +
> +	isb();
> +}
> +

I see in the code below you trust that the tracking will happen with 
PAGE_SIZE granularity (you track with PAGE_SHIFT).

That may be a problem when we have guest memory backed by hugepages or 
transparent huge pages. 

When we are using HDBSS, there is no fault happening, so we have no way of 
doing on-demand block splitting, so we need to make use of eager block 
splitting, _before_ we start to track anything, or else we may have 
different-sized pages in the HDBSS buffer, which is harder to deal with.

Suggestion: do the eager splitting before we enable HDBSS. 

For this to happen, we have to enable the EAGER_SPLIT_CHUNK_SIZE 
capability, which can only be enabled when all memslots are empty.

I suggest doing that at kvm_init_stage2_mmu(), and checking if HDBSS is 
in which case we set mmu->split_page_chunk_size to PAGESIZE.

I will send a patch you can put before this one to make sure it works :)

Thanks!
Leo


>  void kvm_vcpu_load_vhe(struct kvm_vcpu *vcpu)
>  {
>  	host_data_ptr(host_ctxt)->__hyp_running_vcpu = vcpu;
> @@ -220,10 +237,12 @@ void kvm_vcpu_load_vhe(struct kvm_vcpu *vcpu)
>  	__vcpu_load_switch_sysregs(vcpu);
>  	__vcpu_load_activate_traps(vcpu);
>  	__load_stage2(vcpu->arch.hw_mmu, vcpu->arch.hw_mmu->arch);
> +	__load_hdbss(vcpu);
>  }
> 
>  void kvm_vcpu_put_vhe(struct kvm_vcpu *vcpu)
>  {
> +	kvm_flush_hdbss_buffer(vcpu);
>  	__vcpu_put_deactivate_traps(vcpu);
>  	__vcpu_put_switch_sysregs(vcpu);
> 
> diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
> index 070a01e53fcb..42b0710a16ce 100644
> --- a/arch/arm64/kvm/mmu.c
> +++ b/arch/arm64/kvm/mmu.c
> @@ -1896,6 +1896,9 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
>  	if (writable)
>  		prot |= KVM_PGTABLE_PROT_W;
> 
> +	if (writable && kvm->arch.enable_hdbss && logging_active)
> +		prot |= KVM_PGTABLE_PROT_DBM;
> +
>  	if (exec_fault)
>  		prot |= KVM_PGTABLE_PROT_X;
> 
> @@ -2033,6 +2036,70 @@ int kvm_handle_guest_sea(struct kvm_vcpu *vcpu)
>  	return 0;
>  }
> 
> +void kvm_flush_hdbss_buffer(struct kvm_vcpu *vcpu)
> +{
> +	int idx, curr_idx;
> +	u64 br_el2;
> +	u64 *hdbss_buf;
> +	struct kvm *kvm = vcpu->kvm;
> +
> +	if (!kvm->arch.enable_hdbss)
> +		return;
> +
> +	curr_idx = HDBSSPROD_IDX(read_sysreg_s(SYS_HDBSSPROD_EL2));
> +	br_el2 = HDBSSBR_EL2(vcpu->arch.hdbss.base_phys, vcpu->arch.hdbss.size);
> +
> +	/* Do nothing if HDBSS buffer is empty or br_el2 is NULL */
> +	if (curr_idx == 0 || br_el2 == 0)
> +		return;
> +
> +	hdbss_buf = page_address(phys_to_page(vcpu->arch.hdbss.base_phys));
> +	if (!hdbss_buf)
> +		return;
> +
> +	guard(write_lock_irqsave)(&vcpu->kvm->mmu_lock);
> +	for (idx = 0; idx < curr_idx; idx++) {
> +		u64 gpa;
> +
> +		gpa = hdbss_buf[idx];
> +		if (!(gpa & HDBSS_ENTRY_VALID))
> +			continue;
> +
> +		gpa &= HDBSS_ENTRY_IPA;
> +		kvm_vcpu_mark_page_dirty(vcpu, gpa >> PAGE_SHIFT);
> +	}

Here ^

> +
> +	/* reset HDBSS index */
> +	write_sysreg_s(0, SYS_HDBSSPROD_EL2);
> +	vcpu->arch.hdbss.next_index = 0;
> +	isb();
> +}
> +
> +static int kvm_handle_hdbss_fault(struct kvm_vcpu *vcpu)
> +{
> +	u64 prod;
> +	u64 fsc;
> +
> +	prod = read_sysreg_s(SYS_HDBSSPROD_EL2);
> +	fsc = FIELD_GET(HDBSSPROD_EL2_FSC_MASK, prod);
> +
> +	switch (fsc) {
> +	case HDBSSPROD_EL2_FSC_OK:
> +		/* Buffer full, which is reported as permission fault. */
> +		kvm_flush_hdbss_buffer(vcpu);
> +		return 1;
> +	case HDBSSPROD_EL2_FSC_ExternalAbort:
> +	case HDBSSPROD_EL2_FSC_GPF:
> +		return -EFAULT;
> +	default:
> +		/* Unknown fault. */
> +		WARN_ONCE(1,
> +				"Unexpected HDBSS fault type, FSC: 0x%llx (prod=0x%llx, vcpu=%d)\n",
> +				fsc, prod, vcpu->vcpu_id);
> +		return -EFAULT;
> +	}
> +}
> +
>  /**
>   * kvm_handle_guest_abort - handles all 2nd stage aborts
>   * @vcpu:	the VCPU pointer
> @@ -2071,6 +2138,9 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu)
> 
>  	is_iabt = kvm_vcpu_trap_is_iabt(vcpu);
> 
> +	if (esr_iss2_is_hdbssf(esr))
> +		return kvm_handle_hdbss_fault(vcpu);
> +
>  	if (esr_fsc_is_translation_fault(esr)) {
>  		/* Beyond sanitised PARange (which is the IPA limit) */
>  		if (fault_ipa >= BIT_ULL(get_kvm_ipa_limit())) {
> diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
> index 959532422d3a..c03a4b310b53 100644
> --- a/arch/arm64/kvm/reset.c
> +++ b/arch/arm64/kvm/reset.c
> @@ -161,6 +161,9 @@ 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);
> +
> +	if (vcpu->kvm->arch.enable_hdbss)
> +		kvm_arm_vcpu_free_hdbss(vcpu);
>  }
> 
>  static void kvm_vcpu_reset_sve(struct kvm_vcpu *vcpu)
> --
> 2.33.0
> 


^ permalink raw reply

* Re: [PATCH net-next v5 3/3] riscv: dts: eswin: eic7700-hifive-premier-p550: enable Ethernet controller
From: Simon Horman @ 2026-03-25 18:03 UTC (permalink / raw)
  To: lizhi2
  Cc: devicetree, andrew+netdev, davem, edumazet, kuba, robh, krzk+dt,
	conor+dt, netdev, pabeni, mcoquelin.stm32, alexandre.torgue,
	rmk+kernel, pjw, palmer, aou, alex, linux-riscv, linux-stm32,
	linux-arm-kernel, linux-kernel, maxime.chevallier, ningyu, linmin,
	pinkesh.vaghela, pritesh.patel, weishangjuan
In-Reply-To: <20260324073408.439-1-lizhi2@eswincomputing.com>

On Tue, Mar 24, 2026 at 03:34:08PM +0800, lizhi2@eswincomputing.com wrote:
> From: Zhi Li <lizhi2@eswincomputing.com>
> 
> Enable the on-board Gigabit Ethernet controller on the
> HiFive Premier P550 development board.
> 
> Signed-off-by: Zhi Li <lizhi2@eswincomputing.com>
> ---
>  .../dts/eswin/eic7700-hifive-premier-p550.dts | 42 ++++++++++++
>  arch/riscv/boot/dts/eswin/eic7700.dtsi        | 66 +++++++++++++++++++
>  2 files changed, 108 insertions(+)

Unfortunately this does not compile:

$ ARCH=riscv make allmodconfig dtbs
...
  DTC     arch/riscv/boot/dts/eswin/eic7700-hifive-premier-p550.dtb
arch/riscv/boot/dts/eswin/eic7700.dtsi:300.28-330.5: ERROR (phandle_references): /soc/ethernet@50400000: Reference to non-existent node or label "clk"
...

-- 
pw-bot: changes-requested


^ permalink raw reply

* Re: [PATCH v2 01/11] arm64: Skip update of an idreg field affected by an override
From: Catalin Marinas @ 2026-03-25 17:51 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: Marc Zyngier, linux-arm-kernel, kvmarm, Fuad Tabba, Will Deacon,
	Mark Rutland, Joey Gouly, Oliver Upton, Zenghui Yu
In-Reply-To: <a35839df-74a0-46b3-b5e8-7e0a066b210d@arm.com>

On Wed, Mar 25, 2026 at 02:54:28PM +0000, Suzuki K Poulose wrote:
> On 19/03/2026 15:34, Catalin Marinas wrote:
> > On Mon, Mar 02, 2026 at 11:56:42AM +0000, Marc Zyngier wrote:
> > > When computing the new value od an idreg that contains a field
> > > affected by an override, do not update that particular field.
> > > 
> > > The value computed at init-time must be kept as-is, as that's
> > > what the user has asked for, for better or worse.
> > > 
> > > Signed-off-by: Marc Zyngier <maz@kernel.org>
> > > ---
> > >   arch/arm64/kernel/cpufeature.c | 7 +++++++
> > >   1 file changed, 7 insertions(+)
> > > 
> > > diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> > > index c31f8e17732a3..28fc77443ccd3 100644
> > > --- a/arch/arm64/kernel/cpufeature.c
> > > +++ b/arch/arm64/kernel/cpufeature.c
> > > @@ -1224,6 +1224,13 @@ static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
> > >   		s64 ftr_cur = arm64_ftr_value(ftrp, reg->sys_val);
> > >   		s64 ftr_new = arm64_ftr_value(ftrp, new);
> > > +		/*
> > > +		 * Don't alter the initial value that has been forced
> > > +		 * by an override.
> > > +		 */
> > > +		if ((reg->override->mask & arm64_ftr_mask(ftrp)) == arm64_ftr_mask(ftrp))
> > > +			continue;
> > 
> > I got lost in the in the cpufeature framework, so I may be missing
> > something.
> > 
> > Let's say the primary CPU has a feature field with value 2 and we want
> > to override it to value 1. For e.g. a LOWER_SAFE feature, boot_cpu_data
> > will stored the overridden value of 1.
> > 
> > A secondary CPU comes online with the same feature missing, so value 0.
> > With the above change, we no longer update the system-wide feature
> > value, leave it as 1. Later on, for a system feature we may turn it on
> > even though the secondary CPU does not support it.
> > 
> > In summary, this makes the overridden field sticky for secondary CPUs
> > even if they don't support it.
> 
> That is true. I think we should let the secondary CPUs alter the values,
> with initial CPU feature value with the override value set, the system
> could then choose the safest among the override and the others.

It works for me. We should add a comment somewhere that the override is
not expected to work for features where we allow differences (some
FTR_NONSTRICT).

> > Unrelated to your patch, I think we can similarly fail to reject
> > secondary CPUs in check_early_cpu_features() -> verify_local_cpu_caps()
> > because of __read_sysreg_by_encoding() which uses the override value
> > unconditionally. From this perspective, we are now consistent with your
> > patch above.
> 
> This is true as well and the override takes the priority and with the
> wrong level of override value the system could be made to think that
> some features are available even when it is unsafe to do so.
> We should sanitise the values read by __read_sysreg_by_encoding() with
> the "overrides". I can cook something up.

Or remove this check if we expect the override to only work on the
resulting sanitised value, not individual checks.

-- 
Catalin


^ permalink raw reply

* [PATCH] soc: brcmstb: consolidate initcall functions
From: justin.chen @ 2026-03-25 17:46 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: kees, bcm-kernel-feedback-list, florian.fainelli, Justin Chen

From: Justin Chen <justin.chen@broadcom.com>

Merge the separate early_initcall and arch_initcall functions into a
single early_initcall. This is possible thanks to commit 6e12db376b60
("base: soc: Allow early registration of a single SoC device"), which
allows soc_device_register() to be called during early_initcall by
deferring the actual registration until the soc_bus is ready.

Replace static family_id/product_id variables with a dynamically
allocated brcmstb_soc_info structure.

Signed-off-by: Justin Chen <justin.chen@broadcom.com>
---
 drivers/soc/bcm/brcmstb/common.c | 88 +++++++++++++++++---------------
 1 file changed, 46 insertions(+), 42 deletions(-)

diff --git a/drivers/soc/bcm/brcmstb/common.c b/drivers/soc/bcm/brcmstb/common.c
index 2da79bd42930..7be0374f5943 100644
--- a/drivers/soc/bcm/brcmstb/common.c
+++ b/drivers/soc/bcm/brcmstb/common.c
@@ -11,18 +11,22 @@
 #include <linux/soc/brcmstb/brcmstb.h>
 #include <linux/sys_soc.h>
 
-static u32 family_id;
-static u32 product_id;
+struct brcmstb_soc_info {
+	u32 family_id;
+	u32 product_id;
+};
+
+static struct brcmstb_soc_info *soc_info;
 
 u32 brcmstb_get_family_id(void)
 {
-	return family_id;
+	return soc_info ? soc_info->family_id : 0;
 }
 EXPORT_SYMBOL(brcmstb_get_family_id);
 
 u32 brcmstb_get_product_id(void)
 {
-	return product_id;
+	return soc_info ? soc_info->product_id : 0;
 }
 EXPORT_SYMBOL(brcmstb_get_product_id);
 
@@ -40,10 +44,12 @@ static const struct of_device_id sun_top_ctrl_match[] = {
 	{ }
 };
 
-static int __init brcmstb_soc_device_early_init(void)
+static int __init brcmstb_soc_device_init(void)
 {
+	struct soc_device_attribute *soc_dev_attr;
 	struct device_node *sun_top_ctrl;
 	void __iomem *sun_top_ctrl_base;
+	struct soc_device *soc_dev;
 	int ret = 0;
 
 	/* We could be on a multi-platform kernel, don't make this fatal but
@@ -51,63 +57,61 @@ static int __init brcmstb_soc_device_early_init(void)
 	 */
 	sun_top_ctrl = of_find_matching_node(NULL, sun_top_ctrl_match);
 	if (!sun_top_ctrl)
-		return ret;
+		return 0;
 
 	sun_top_ctrl_base = of_iomap(sun_top_ctrl, 0);
 	if (!sun_top_ctrl_base) {
 		ret = -ENODEV;
-		goto out;
+		goto out_put_node;
 	}
 
-	family_id = readl(sun_top_ctrl_base);
-	product_id = readl(sun_top_ctrl_base + 0x4);
-	iounmap(sun_top_ctrl_base);
-out:
-	of_node_put(sun_top_ctrl);
-	return ret;
-}
-early_initcall(brcmstb_soc_device_early_init);
-
-static int __init brcmstb_soc_device_init(void)
-{
-	struct soc_device_attribute *soc_dev_attr;
-	struct device_node *sun_top_ctrl;
-	struct soc_device *soc_dev;
-	int ret = 0;
+	soc_info = kzalloc(sizeof(*soc_info), GFP_KERNEL);
+	if (!soc_info) {
+		ret = -ENOMEM;
+		goto out_unmap;
+	}
 
-	/* We could be on a multi-platform kernel, don't make this fatal but
-	 * bail out early
-	 */
-	sun_top_ctrl = of_find_matching_node(NULL, sun_top_ctrl_match);
-	if (!sun_top_ctrl)
-		return ret;
+	soc_info->family_id = readl(sun_top_ctrl_base);
+	soc_info->product_id = readl(sun_top_ctrl_base + 0x4);
 
 	soc_dev_attr = kzalloc_obj(*soc_dev_attr);
 	if (!soc_dev_attr) {
 		ret = -ENOMEM;
-		goto out;
+		goto out_free_info;
 	}
 
 	soc_dev_attr->family = kasprintf(GFP_KERNEL, "%x",
-					 family_id >> 28 ?
-					 family_id >> 16 : family_id >> 8);
+					 soc_info->family_id >> 28 ?
+					 soc_info->family_id >> 16 : soc_info->family_id >> 8);
 	soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%x",
-					 product_id >> 28 ?
-					 product_id >> 16 : product_id >> 8);
+					 soc_info->product_id >> 28 ?
+					 soc_info->product_id >> 16 : soc_info->product_id >> 8);
 	soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%c%d",
-					 ((product_id & 0xf0) >> 4) + 'A',
-					   product_id & 0xf);
+					 ((soc_info->product_id & 0xf0) >> 4) + 'A',
+					   soc_info->product_id & 0xf);
 
 	soc_dev = soc_device_register(soc_dev_attr);
 	if (IS_ERR(soc_dev)) {
-		kfree(soc_dev_attr->family);
-		kfree(soc_dev_attr->soc_id);
-		kfree(soc_dev_attr->revision);
-		kfree(soc_dev_attr);
-		ret = -ENOMEM;
+		ret = PTR_ERR(soc_dev);
+		goto out_free_attr;
 	}
-out:
+
+	iounmap(sun_top_ctrl_base);
+	of_node_put(sun_top_ctrl);
+	return 0;
+
+out_free_attr:
+	kfree(soc_dev_attr->revision);
+	kfree(soc_dev_attr->soc_id);
+	kfree(soc_dev_attr->family);
+	kfree(soc_dev_attr);
+out_free_info:
+	kfree(soc_info);
+	soc_info = NULL;
+out_unmap:
+	iounmap(sun_top_ctrl_base);
+out_put_node:
 	of_node_put(sun_top_ctrl);
 	return ret;
 }
-arch_initcall(brcmstb_soc_device_init);
+early_initcall(brcmstb_soc_device_init);
-- 
2.34.1



^ permalink raw reply related

* Re: [PATCH v3 3/9] media: rockchip: rkcif: add support for rk3588 vicap mipi capture
From: Mehdi Djait @ 2026-03-25 17:38 UTC (permalink / raw)
  To: michael.riesch
  Cc: Laurent Pinchart, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner, Kever Yang,
	Jagan Teki,
	Кузнецов Михаил,
	Charalampos Mitrodimas, Sebastian Reichel, Nicolas Dufresne,
	Collabora Kernel Team, Sakari Ailus, linux-media, devicetree,
	linux-arm-kernel, linux-rockchip, linux-kernel
In-Reply-To: <20250430-rk3588-vicap-v3-3-e38e428868cc@collabora.com>

Hi Michael,

Thank you for the patch!

On Wed, Mar 25, 2026 at 12:51:08PM +0100, Michael Riesch via B4 Relay wrote:
> From: Michael Riesch <michael.riesch@collabora.com>
> 
> The RK3588 Video Capture (VICAP) unit features a Digital Video Port
> (DVP) and six MIPI CSI-2 capture interfaces. Add initial support
> for this variant to the rkcif driver and enable the MIPI CSI-2
> capture interfaces.
> 

Reviewed-by: Mehdi Djait <mehdi.djait@linux.intel.com>

> Signed-off-by: Michael Riesch <michael.riesch@collabora.com>
> ---
>  .../platform/rockchip/rkcif/rkcif-capture-mipi.c   | 141 +++++++++++++++++++++
>  .../platform/rockchip/rkcif/rkcif-capture-mipi.h   |   1 +
>  .../media/platform/rockchip/rkcif/rkcif-common.h   |   2 +-
>  drivers/media/platform/rockchip/rkcif/rkcif-dev.c  |  18 +++
>  4 files changed, 161 insertions(+), 1 deletion(-)

--
Kind Regards
Mehdi Djait


^ permalink raw reply

* Re: [PATCH v1 2/3] arm64: mm: Handle invalid large leaf mappings correctly
From: Ryan Roberts @ 2026-03-25 17:37 UTC (permalink / raw)
  To: Yang Shi, Catalin Marinas, Will Deacon, David Hildenbrand (Arm),
	Dev Jain, Suzuki K Poulose, Jinjiang Tu, Kevin Brodsky
  Cc: linux-arm-kernel, linux-kernel, stable
In-Reply-To: <401073fd-3438-419d-8287-35eea61919b0@os.amperecomputing.com>

On 24/03/2026 18:20, Yang Shi wrote:
> 
> 
> On 3/23/26 6:03 AM, Ryan Roberts wrote:
>> It has been possible for a long time to mark ptes in the linear map as
>> invalid. This is done for secretmem, kfence, realm dma memory un/share,
>> and others, by simply clearing the PTE_VALID bit. But until commit
>> a166563e7ec37 ("arm64: mm: support large block mapping when
>> rodata=full") large leaf mappings were never made invalid in this way.
>>
>> It turns out various parts of the code base are not equipped to handle
>> invalid large leaf mappings (in the way they are currently encoded) and
>> I've observed a kernel panic while booting a realm guest on a
>> BBML2_NOABORT system as a result:
>>
>> [   15.432706] software IO TLB: Memory encryption is active and system is
>> using DMA bounce buffers
>> [   15.476896] Unable to handle kernel paging request at virtual address
>> ffff000019600000
>> [   15.513762] Mem abort info:
>> [   15.527245]   ESR = 0x0000000096000046
>> [   15.548553]   EC = 0x25: DABT (current EL), IL = 32 bits
>> [   15.572146]   SET = 0, FnV = 0
>> [   15.592141]   EA = 0, S1PTW = 0
>> [   15.612694]   FSC = 0x06: level 2 translation fault
>> [   15.640644] Data abort info:
>> [   15.661983]   ISV = 0, ISS = 0x00000046, ISS2 = 0x00000000
>> [   15.694875]   CM = 0, WnR = 1, TnD = 0, TagAccess = 0
>> [   15.723740]   GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
>> [   15.755776] swapper pgtable: 4k pages, 48-bit VAs, pgdp=0000000081f3f000
>> [   15.800410] [ffff000019600000] pgd=0000000000000000, p4d=180000009ffff403,
>> pud=180000009fffe403, pmd=00e8000199600704
>> [   15.855046] Internal error: Oops: 0000000096000046 [#1]  SMP
>> [   15.886394] Modules linked in:
>> [   15.900029] CPU: 0 UID: 0 PID: 1 Comm: swapper/0 Not tainted 7.0.0-rc4-
>> dirty #4 PREEMPT
>> [   15.935258] Hardware name: linux,dummy-virt (DT)
>> [   15.955612] pstate: 21400005 (nzCv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--)
>> [   15.986009] pc : __pi_memcpy_generic+0x128/0x22c
>> [   16.006163] lr : swiotlb_bounce+0xf4/0x158
>> [   16.024145] sp : ffff80008000b8f0
>> [   16.038896] x29: ffff80008000b8f0 x28: 0000000000000000 x27: 0000000000000000
>> [   16.069953] x26: ffffb3976d261ba8 x25: 0000000000000000 x24: ffff000019600000
>> [   16.100876] x23: 0000000000000001 x22: ffff0000043430d0 x21: 0000000000007ff0
>> [   16.131946] x20: 0000000084570010 x19: 0000000000000000 x18: ffff00001ffe3fcc
>> [   16.163073] x17: 0000000000000000 x16: 00000000003fffff x15: 646e612065766974
>> [   16.194131] x14: 0000000000000000 x13: 0000000000000000 x12: 0000000000000000
>> [   16.225059] x11: 0000000000000000 x10: 0000000000000010 x9 : 0000000000000018
>> [   16.256113] x8 : 0000000000000018 x7 : 0000000000000000 x6 : 0000000000000000
>> [   16.287203] x5 : ffff000019607ff0 x4 : ffff000004578000 x3 : ffff000019600000
>> [   16.318145] x2 : 0000000000007ff0 x1 : ffff000004570010 x0 : ffff000019600000
>> [   16.349071] Call trace:
>> [   16.360143]  __pi_memcpy_generic+0x128/0x22c (P)
>> [   16.380310]  swiotlb_tbl_map_single+0x154/0x2b4
>> [   16.400282]  swiotlb_map+0x5c/0x228
>> [   16.415984]  dma_map_phys+0x244/0x2b8
>> [   16.432199]  dma_map_page_attrs+0x44/0x58
>> [   16.449782]  virtqueue_map_page_attrs+0x38/0x44
>> [   16.469596]  virtqueue_map_single_attrs+0xc0/0x130
>> [   16.490509]  virtnet_rq_alloc.isra.0+0xa4/0x1fc
>> [   16.510355]  try_fill_recv+0x2a4/0x584
>> [   16.526989]  virtnet_open+0xd4/0x238
>> [   16.542775]  __dev_open+0x110/0x24c
>> [   16.558280]  __dev_change_flags+0x194/0x20c
>> [   16.576879]  netif_change_flags+0x24/0x6c
>> [   16.594489]  dev_change_flags+0x48/0x7c
>> [   16.611462]  ip_auto_config+0x258/0x1114
>> [   16.628727]  do_one_initcall+0x80/0x1c8
>> [   16.645590]  kernel_init_freeable+0x208/0x2f0
>> [   16.664917]  kernel_init+0x24/0x1e0
>> [   16.680295]  ret_from_fork+0x10/0x20
>> [   16.696369] Code: 927cec03 cb0e0021 8b0e0042 a9411c26 (a900340c)
>> [   16.723106] ---[ end trace 0000000000000000 ]---
>> [   16.752866] Kernel panic - not syncing: Attempted to kill init!
>> exitcode=0x0000000b
>> [   16.792556] Kernel Offset: 0x3396ea200000 from 0xffff800080000000
>> [   16.818966] PHYS_OFFSET: 0xfff1000080000000
>> [   16.837237] CPU features: 0x0000000,00060005,13e38581,957e772f
>> [   16.862904] Memory Limit: none
>> [   16.876526] ---[ end Kernel panic - not syncing: Attempted to kill init!
>> exitcode=0x0000000b ]---
>>
>> This panic occurs because the swiotlb memory was previously shared to
>> the host (__set_memory_enc_dec()), which involves transitioning the
>> (large) leaf mappings to invalid, sharing to the host, then marking the
>> mappings valid again. But pageattr_p[mu]d_entry() would only update the
>> entry if it is a section mapping, since otherwise it concluded it must
>> be a table entry so shouldn't be modified. But p[mu]d_sect() only
>> returns true if the entry is valid. So the result was that the large
>> leaf entry was made invalid in the first pass then ignored in the second
>> pass. It remains invalid until the above code tries to access it and
>> blows up.
> 
> Good catch. I recall I met this problem when I worked on a very early PoC of
> large block mapping patch. It took a total different approach than
> BBML2_NOABORT. I didn't run into that problem when I implemented BBML2_NOABORT
> because nobody actually changed valid/invalid attribute on large block mapping
> granule so I forgot it. But I definitely missed realm usecase.
> 
>>
>> The simple fix would be to update pageattr_pmd_entry() to use
>> !pmd_table() instead of pmd_sect(). That would solve this problem.
> 
> Yes, I agree.
> 
>>
>> But the ptdump code also suffers from a similar issue. It checks
>> pmd_leaf() and doesn't call into the arch-specific note_page() machinery
>> if it returns false. As a result of this, ptdump wasn't even able to
>> show the invalid large leaf mappings; it looked like they were valid
>> which made this super fun to debug. the ptdump code is core-mm and
>> pmd_table() is arm64-specific so we can't use the same trick to solve
>> that.
> 
> I don't quite get why we need to show invalid mappings in ptdump? IIUC ptdump is
> not supposed to show invalid mappings even though they are transient.

Let's say we have 8M of PMD mappings, then we want to mark 2M in the middle of
that as invalid. Prior to my fix, ptdump would show the full 8M as still being
valid after making the middle 2M invalid. This happened because the note_page()
call for the 2M invalid part was suppressed, but there was also no ptdump_hole()
call since the PMD entry is not none. After my fix, we call note_page() for the
non-none but invalid pmd and now the "F" is correctly displayed for that portion.

Thanks,
Ryan



> 
> Thanks,
> Yang
> 
> 
>>
>> But we already support the concept of "present-invalid" for user space
>> entries. And even better, pmd_leaf() will return true for a leaf mapping
>> that is marked present-invalid. So let's just use that encoding for
>> present-invalid kernel mappings too. Then we can use pmd_leaf() where we
>> previously used pmd_sect() and everything is magically fixed.
>>
>> Additionally, from inspection kernel_page_present() was broken in a
>> similar way, so I'm also updating that to use pmd_leaf().
>>
>> I haven't spotted any other issues of this shape but plan to do a follow
>> up patch to remove pmd_sect() and pud_sect() in favour of the more
>> sophisticated pmd_leaf()/pud_leaf() which are core-mm APIs and will
>> simplify arm64 code a bit.
>>
>> Fixes: a166563e7ec37 ("arm64: mm: support large block mapping when rodata=full")
>> Cc: stable@vger.kernel.org
>> Signed-off-by: Ryan Roberts <ryan.roberts@arm.com>
>> ---
>>   arch/arm64/mm/pageattr.c | 50 ++++++++++++++++++++++------------------
>>   1 file changed, 28 insertions(+), 22 deletions(-)
>>
>> diff --git a/arch/arm64/mm/pageattr.c b/arch/arm64/mm/pageattr.c
>> index 358d1dc9a576f..87dfe4c82fa92 100644
>> --- a/arch/arm64/mm/pageattr.c
>> +++ b/arch/arm64/mm/pageattr.c
>> @@ -25,6 +25,11 @@ static ptdesc_t set_pageattr_masks(ptdesc_t val, struct
>> mm_walk *walk)
>>   {
>>       struct page_change_data *masks = walk->private;
>>   +    /*
>> +     * Some users clear and set bits which alias eachother (e.g. PTE_NG and
>> +     * PTE_PRESENT_INVALID). It is therefore important that we always clear
>> +     * first then set.
>> +     */
>>       val &= ~(pgprot_val(masks->clear_mask));
>>       val |= (pgprot_val(masks->set_mask));
>>   @@ -36,7 +41,7 @@ static int pageattr_pud_entry(pud_t *pud, unsigned long addr,
>>   {
>>       pud_t val = pudp_get(pud);
>>   -    if (pud_sect(val)) {
>> +    if (pud_leaf(val)) {
>>           if (WARN_ON_ONCE((next - addr) != PUD_SIZE))
>>               return -EINVAL;
>>           val = __pud(set_pageattr_masks(pud_val(val), walk));
>> @@ -52,7 +57,7 @@ static int pageattr_pmd_entry(pmd_t *pmd, unsigned long addr,
>>   {
>>       pmd_t val = pmdp_get(pmd);
>>   -    if (pmd_sect(val)) {
>> +    if (pmd_leaf(val)) {
>>           if (WARN_ON_ONCE((next - addr) != PMD_SIZE))
>>               return -EINVAL;
>>           val = __pmd(set_pageattr_masks(pmd_val(val), walk));
>> @@ -132,11 +137,12 @@ static int __change_memory_common(unsigned long start,
>> unsigned long size,
>>       ret = update_range_prot(start, size, set_mask, clear_mask);
>>         /*
>> -     * If the memory is being made valid without changing any other bits
>> -     * then a TLBI isn't required as a non-valid entry cannot be cached in
>> -     * the TLB.
>> +     * If the memory is being switched from present-invalid to valid without
>> +     * changing any other bits then a TLBI isn't required as a non-valid
>> +     * entry cannot be cached in the TLB.
>>        */
>> -    if (pgprot_val(set_mask) != PTE_VALID || pgprot_val(clear_mask))
>> +    if (pgprot_val(set_mask) != (PTE_MAYBE_NG | PTE_VALID) ||
>> +        pgprot_val(clear_mask) != PTE_PRESENT_INVALID)
>>           flush_tlb_kernel_range(start, start + size);
>>       return ret;
>>   }
>> @@ -237,18 +243,18 @@ int set_memory_valid(unsigned long addr, int numpages,
>> int enable)
>>   {
>>       if (enable)
>>           return __change_memory_common(addr, PAGE_SIZE * numpages,
>> -                    __pgprot(PTE_VALID),
>> -                    __pgprot(0));
>> +                    __pgprot(PTE_MAYBE_NG | PTE_VALID),
>> +                    __pgprot(PTE_PRESENT_INVALID));
>>       else
>>           return __change_memory_common(addr, PAGE_SIZE * numpages,
>> -                    __pgprot(0),
>> -                    __pgprot(PTE_VALID));
>> +                    __pgprot(PTE_PRESENT_INVALID),
>> +                    __pgprot(PTE_MAYBE_NG | PTE_VALID));
>>   }
>>     int set_direct_map_invalid_noflush(struct page *page)
>>   {
>> -    pgprot_t clear_mask = __pgprot(PTE_VALID);
>> -    pgprot_t set_mask = __pgprot(0);
>> +    pgprot_t clear_mask = __pgprot(PTE_MAYBE_NG | PTE_VALID);
>> +    pgprot_t set_mask = __pgprot(PTE_PRESENT_INVALID);
>>         if (!can_set_direct_map())
>>           return 0;
>> @@ -259,8 +265,8 @@ int set_direct_map_invalid_noflush(struct page *page)
>>     int set_direct_map_default_noflush(struct page *page)
>>   {
>> -    pgprot_t set_mask = __pgprot(PTE_VALID | PTE_WRITE);
>> -    pgprot_t clear_mask = __pgprot(PTE_RDONLY);
>> +    pgprot_t set_mask = __pgprot(PTE_MAYBE_NG | PTE_VALID | PTE_WRITE);
>> +    pgprot_t clear_mask = __pgprot(PTE_PRESENT_INVALID | PTE_RDONLY);
>>         if (!can_set_direct_map())
>>           return 0;
>> @@ -296,8 +302,8 @@ static int __set_memory_enc_dec(unsigned long addr,
>>        * entries or Synchronous External Aborts caused by RIPAS_EMPTY
>>        */
>>       ret = __change_memory_common(addr, PAGE_SIZE * numpages,
>> -                     __pgprot(set_prot),
>> -                     __pgprot(clear_prot | PTE_VALID));
>> +                     __pgprot(set_prot | PTE_PRESENT_INVALID),
>> +                     __pgprot(clear_prot | PTE_MAYBE_NG | PTE_VALID));
>>         if (ret)
>>           return ret;
>> @@ -311,8 +317,8 @@ static int __set_memory_enc_dec(unsigned long addr,
>>           return ret;
>>         return __change_memory_common(addr, PAGE_SIZE * numpages,
>> -                      __pgprot(PTE_VALID),
>> -                      __pgprot(0));
>> +                      __pgprot(PTE_MAYBE_NG | PTE_VALID),
>> +                      __pgprot(PTE_PRESENT_INVALID));
>>   }
>>     static int realm_set_memory_encrypted(unsigned long addr, int numpages)
>> @@ -404,15 +410,15 @@ bool kernel_page_present(struct page *page)
>>       pud = READ_ONCE(*pudp);
>>       if (pud_none(pud))
>>           return false;
>> -    if (pud_sect(pud))
>> -        return true;
>> +    if (pud_leaf(pud))
>> +        return pud_valid(pud);
>>         pmdp = pmd_offset(pudp, addr);
>>       pmd = READ_ONCE(*pmdp);
>>       if (pmd_none(pmd))
>>           return false;
>> -    if (pmd_sect(pmd))
>> -        return true;
>> +    if (pmd_leaf(pmd))
>> +        return pmd_valid(pmd);
>>         ptep = pte_offset_kernel(pmdp, addr);
>>       return pte_valid(__ptep_get(ptep));
> 



^ permalink raw reply

* Re: [PATCH v3 3/7] pinctrl: pinctrl-generic: add __pinctrl_generic_pins_function_dt_node_to_map()
From: Conor Dooley @ 2026-03-25 17:34 UTC (permalink / raw)
  To: Frank Li
  Cc: Linus Walleij, Peter Rosin, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Rafał Miłecki, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, linux-kernel, linux-gpio,
	devicetree, imx, linux-arm-kernel, Haibo Chen
In-Reply-To: <acP6oFsaD8PddWjg@lizhi-Precision-Tower-5810>

[-- Attachment #1: Type: text/plain, Size: 9535 bytes --]

On Wed, Mar 25, 2026 at 11:09:20AM -0400, Frank Li wrote:
> On Wed, Mar 25, 2026 at 10:33:05AM +0000, Conor Dooley wrote:
> > On Tue, Mar 24, 2026 at 04:16:10PM -0400, Frank Li wrote:
> > > On Fri, Mar 20, 2026 at 09:54:45AM -0400, Frank Li wrote:
> > > > On Fri, Mar 20, 2026 at 02:27:21PM +0100, Linus Walleij wrote:
> > > > > On Thu, Mar 19, 2026 at 12:04 AM Frank Li <Frank.li@nxp.com> wrote:
> > > > > > On Mon, Mar 16, 2026 at 10:37:28AM +0100, Linus Walleij wrote:
> > > > >
> > > > > > > That said: in this case you're just adding a parameter, just add
> > > > > > > the parameter and change all of the in-tree users to pass false
> > > > > > > or whatever you need, these is just one (1) in-tree user anyway.
> > > > > >
> > > > > > pinctrl_generic_pins_function_dt_node_to_map() directly feed to
> > > > > > .dt_node_to_map() callback, add parameter will impact too much.
> > > > >
> > > > > Why do you say that. It already has many parameters, one more
> > > > > or less doesn't matter. It's not like this call is performance-critical.
> > > > > Just change the users.
> > > >
> > > > In only user drivers/pinctrl/microchip/pinctrl-mpfs-mssio.c,
> > > > 	.dt_node_to_map = pinctrl_generic_pins_function_dt_node_to_map;
> > > >
> > > > pinctrl_generic_pins_function_dt_node_to_map() need match .dt_node_to_map()'s
> > > > declear.
> > > >
> > > > So it can't direct add two parameters in pinctrl_generic_pins_function_dt_node_to_map()
> > > > Need simple wrap function, which other in pinctrl-mpfs-mssio.c or in
> > > > pinconf.h.
> > > >
> > > > If add two parameter in .dt_node_to_map(), need change all functions, which
> > > > .dt_node_to_map = xxx_to_map(). and OF core part.
> > >
> > > Linus Walleij:
> > > 	Is my explain clear enough? I am preparing respin it?
> > >
> > > 	is okay use wrap function
> > > 	pinctrl_generic_pins_function_dt_node_to_map_ext()?
> >
> > I don't understand this patch. The function is called
> > pinctrl_generic_pins_function_dt_node_to_map(). You have no pins.
> > You're adding a parameter to make a function with *pins* in its name not
> > use pins. The new function doesn't use pins but has pins in the name.
> > At the very least function names should not be misleading.
> >
> > I was going to suggest pulling out the relevant portions and creating
> > some helpers that could be used by multiple different-but-similar
> > functions, but I don't actually even think that there's much in common.
> > Most damningly I think, you don't actually read either the functions or
> > pins properties at all and neither are permitted by your binding.
> > So turns out you use neither pins or functions...
> >
> > You don't actually have any of these properties which runs counter to the
> > goal of the function, which is parsing. With this in mind, it feels to me
> > like you're trying way too hard to make use of a generic function when the
> > right thing to do is probably just have an entirely custom function.
> > Maybe that's a custom implementation in your driver, or a new function
> > here, but I think writing that will highlight just how little of the
> > code would be shared between the existing function and what your
> > use-case needs: no pin configuration stuff, no reading of the devicetree
> > other than the node names and no dealing with the label pointing to the
> > "wrong" place.
> >
> > I recently bought a spacemit k1 board to go and write a sister function
> > to pinctrl_generic_pins_function_dt_node_to_map() that deals with pins
> > and groups (because that's a pretty common pattern).
> > I would be calling that pinctrl_generic_pinmux_dt_node_to_map(),
> > because it that's the property it deals with. I have honestly got no
> > idea what to call one for this situation since you don't have any of the
> > properties in pinmux-node.yaml. Maybe that's a sign.
> 
> At v2, I implemented customize dt_node_to_map(), Linus Walleij think it is
> too similar with pinctrl_generic_pins_function_dt_node_to_map(), so ask me
> to enhanance and reuse pinctrl_generic_pins_function_dt_node_to_map().

Sure, and he's right that there's a lot similar. Everything you want to
do, other than looking at the mux state, is something that
pinctrl_generic_pins_function_dt_node_to_map() does. But bastardising
a function that's explicitly about reading pins and functions properties
to do things that have _neither_ is not a good implementation of that
review feedback.

If you're going to make something generic, the right level to hook in
IMO is at the pinctrl_generic_pins_function_dt_subnode_to_map() level,
I already know that 95% of the code in that function is identical to
what will be used for the spacemit k1 that uses the pinmux property
and changing its API is a lot easier than changing the API of something
that is written to match the dt_node_to_map callback.
You don't even benefit from the extra functionality that
pinctrl_generic_pins_function_dt_node_to_map() provides, because you
don't have ambiguity about where the phandle you're parsing from points.
In your case, it has to be the group node.

pinctrl_generic_pins_function_dt_subnode_to_map() could probably be
split into two parts, one that does the dt parsing portion and a second
portion that does the mapping to kernel data structures. The first
portion of that is the for loop. The second portion is everything after
the for loop and the bit that names the groups. IOW, do something like
what I am pasting here, and you create your own function that wraps
pinctrl_generic_to_map() in the way you want. I personally think this is
more tasteful than what you've done, and more importantly I am pretty
sure that this is what's needed to be able to maximise code reuse for
the devices that use pinmux. I didn't compile this or anything, it's
just speculative.

diff --git a/drivers/pinctrl/pinctrl-generic.c b/drivers/pinctrl/pinctrl-generic.c
index efb39c6a67033..7f02af6d9f3e4 100644
--- a/drivers/pinctrl/pinctrl-generic.c
+++ b/drivers/pinctrl/pinctrl-generic.c
@@ -17,56 +17,30 @@
 #include "pinctrl-utils.h"
 #include "pinmux.h"
 
-static int pinctrl_generic_pins_function_dt_subnode_to_map(struct pinctrl_dev *pctldev,
-							   struct device_node *parent,
-							   struct device_node *np,
-							   struct pinctrl_map **maps,
-							   unsigned int *num_maps,
-							   unsigned int *num_reserved_maps,
-							   const char **group_names,
-							   unsigned int ngroups)
+static int pinctrl_generic_to_map(struct pinctrl_dev *pctldev,
+				  struct device_node *parent,
+				  struct device_node *np,
+				  struct pinctrl_map **maps,
+				  unsigned int *num_maps,
+				  unsigned int *num_reserved_maps,
+				  const char **group_names,
+				  unsigned int ngroups,
+				  const char **functions,
+				  unsigned int *pins,
+				  void *function_data)
 {
 	struct device *dev = pctldev->dev;
-	const char **functions;
 	const char *group_name;
 	unsigned long *configs;
-	unsigned int num_configs, pin, *pins;
+	unsigned int num_configs;
 	int npins, ret, reserve = 1;
 
-	npins = of_property_count_u32_elems(np, "pins");
-
-	if (npins < 1) {
-		dev_err(dev, "invalid pinctrl group %pOFn.%pOFn %d\n",
-			parent, np, npins);
-		return npins;
-	}
-
 	group_name = devm_kasprintf(dev, GFP_KERNEL, "%pOFn.%pOFn", parent, np);
 	if (!group_name)
 		return -ENOMEM;
 
 	group_names[ngroups] = group_name;
 
-	pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
-	if (!pins)
-		return -ENOMEM;
-
-	functions = devm_kcalloc(dev, npins, sizeof(*functions), GFP_KERNEL);
-	if (!functions)
-		return -ENOMEM;
-
-	for (int i = 0; i < npins; i++) {
-		ret = of_property_read_u32_index(np, "pins", i, &pin);
-		if (ret)
-			return ret;
-
-		pins[i] = pin;
-
-		ret = of_property_read_string(np, "function", &functions[i]);
-		if (ret)
-			return ret;
-	}
-
 	ret = pinctrl_utils_reserve_map(pctldev, maps, num_reserved_maps, num_maps, reserve);
 	if (ret)
 		return ret;
@@ -101,6 +75,52 @@ static int pinctrl_generic_pins_function_dt_subnode_to_map(struct pinctrl_dev *p
 		return ret;
 
 	return 0;
+}
+
+static int pinctrl_generic_pins_function_dt_subnode_to_map(struct pinctrl_dev *pctldev,
+							   struct device_node *parent,
+							   struct device_node *np,
+							   struct pinctrl_map **maps,
+							   unsigned int *num_maps,
+							   unsigned int *num_reserved_maps,
+							   const char **group_names,
+							   unsigned int ngroups)
+{
+	struct device *dev = pctldev->dev;
+	const char **functions;
+	unsigned int pin, *pins;
+	int npins, ret;
+
+	npins = of_property_count_u32_elems(np, "pins");
+
+	if (npins < 1) {
+		dev_err(dev, "invalid pinctrl group %pOFn.%pOFn %d\n",
+			parent, np, npins);
+		return npins;
+	}
+
+	pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
+	if (!pins)
+		return -ENOMEM;
+
+	functions = devm_kcalloc(dev, npins, sizeof(*functions), GFP_KERNEL);
+	if (!functions)
+		return -ENOMEM;
+
+	for (int i = 0; i < npins; i++) {
+		ret = of_property_read_u32_index(np, "pins", i, &pin);
+		if (ret)
+			return ret;
+
+		pins[i] = pin;
+
+		ret = of_property_read_string(np, "function", &functions[i]);
+		if (ret)
+			return ret;
+	}
+	return pinctrl_generic_to_map(pctldev, parent, np, maps, num_maps,
+				  num_reserved_maps, group_names, ngroups,
+				  functions, pins, NULL);
 };
 
 /*



[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply related

* Re: [PATCH v1 0/2] i2c: imx: fix i2c issues when reading messages
From: Andi Shyti @ 2026-03-25 17:32 UTC (permalink / raw)
  To: Stefan Eichenberger
  Cc: o.rempel, kernel, Frank.Li, s.hauer, festevam,
	stefan.eichenberger, francesco.dolcini, linux-i2c, imx,
	linux-arm-kernel, linux-kernel
In-Reply-To: <20260218150940.131354-1-eichest@gmail.com>

Hi Stefan,

> Stefan Eichenberger (2):
>   i2c: imx: fix i2c issue when reading multiple messages
>   i2c: imx: ensure no clock is generated after last read

merged to i2c/i2c-host-fixes.

Thanks,
Andi


^ permalink raw reply

* Re: [PATCH v1 2/3] arm64: mm: Handle invalid large leaf mappings correctly
From: Ryan Roberts @ 2026-03-25 17:31 UTC (permalink / raw)
  To: Jinjiang Tu, Catalin Marinas, Will Deacon,
	David Hildenbrand (Arm), Dev Jain, Yang Shi, Suzuki K Poulose,
	Kevin Brodsky
  Cc: linux-arm-kernel, linux-kernel, stable
In-Reply-To: <a7fa6fd9-79b2-4e46-8ee4-fde9d5853100@huawei.com>

On 24/03/2026 02:30, Jinjiang Tu wrote:
> 
> 在 2026/3/23 21:03, Ryan Roberts 写道:
>> It has been possible for a long time to mark ptes in the linear map as
>> invalid. This is done for secretmem, kfence, realm dma memory un/share,
>> and others, by simply clearing the PTE_VALID bit. But until commit
>> a166563e7ec37 ("arm64: mm: support large block mapping when
>> rodata=full") large leaf mappings were never made invalid in this way.
>>
>> It turns out various parts of the code base are not equipped to handle
>> invalid large leaf mappings (in the way they are currently encoded) and
>> I've observed a kernel panic while booting a realm guest on a
>> BBML2_NOABORT system as a result:
>>
>> [   15.432706] software IO TLB: Memory encryption is active and system is
>> using DMA bounce buffers
>> [   15.476896] Unable to handle kernel paging request at virtual address
>> ffff000019600000
>> [   15.513762] Mem abort info:
>> [   15.527245]   ESR = 0x0000000096000046
>> [   15.548553]   EC = 0x25: DABT (current EL), IL = 32 bits
>> [   15.572146]   SET = 0, FnV = 0
>> [   15.592141]   EA = 0, S1PTW = 0
>> [   15.612694]   FSC = 0x06: level 2 translation fault
>> [   15.640644] Data abort info:
>> [   15.661983]   ISV = 0, ISS = 0x00000046, ISS2 = 0x00000000
>> [   15.694875]   CM = 0, WnR = 1, TnD = 0, TagAccess = 0
>> [   15.723740]   GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
>> [   15.755776] swapper pgtable: 4k pages, 48-bit VAs, pgdp=0000000081f3f000
>> [   15.800410] [ffff000019600000] pgd=0000000000000000, p4d=180000009ffff403,
>> pud=180000009fffe403, pmd=00e8000199600704
>> [   15.855046] Internal error: Oops: 0000000096000046 [#1]  SMP
>> [   15.886394] Modules linked in:
>> [   15.900029] CPU: 0 UID: 0 PID: 1 Comm: swapper/0 Not tainted 7.0.0-rc4-
>> dirty #4 PREEMPT
>> [   15.935258] Hardware name: linux,dummy-virt (DT)
>> [   15.955612] pstate: 21400005 (nzCv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--)
>> [   15.986009] pc : __pi_memcpy_generic+0x128/0x22c
>> [   16.006163] lr : swiotlb_bounce+0xf4/0x158
>> [   16.024145] sp : ffff80008000b8f0
>> [   16.038896] x29: ffff80008000b8f0 x28: 0000000000000000 x27: 0000000000000000
>> [   16.069953] x26: ffffb3976d261ba8 x25: 0000000000000000 x24: ffff000019600000
>> [   16.100876] x23: 0000000000000001 x22: ffff0000043430d0 x21: 0000000000007ff0
>> [   16.131946] x20: 0000000084570010 x19: 0000000000000000 x18: ffff00001ffe3fcc
>> [   16.163073] x17: 0000000000000000 x16: 00000000003fffff x15: 646e612065766974
>> [   16.194131] x14: 0000000000000000 x13: 0000000000000000 x12: 0000000000000000
>> [   16.225059] x11: 0000000000000000 x10: 0000000000000010 x9 : 0000000000000018
>> [   16.256113] x8 : 0000000000000018 x7 : 0000000000000000 x6 : 0000000000000000
>> [   16.287203] x5 : ffff000019607ff0 x4 : ffff000004578000 x3 : ffff000019600000
>> [   16.318145] x2 : 0000000000007ff0 x1 : ffff000004570010 x0 : ffff000019600000
>> [   16.349071] Call trace:
>> [   16.360143]  __pi_memcpy_generic+0x128/0x22c (P)
>> [   16.380310]  swiotlb_tbl_map_single+0x154/0x2b4
>> [   16.400282]  swiotlb_map+0x5c/0x228
>> [   16.415984]  dma_map_phys+0x244/0x2b8
>> [   16.432199]  dma_map_page_attrs+0x44/0x58
>> [   16.449782]  virtqueue_map_page_attrs+0x38/0x44
>> [   16.469596]  virtqueue_map_single_attrs+0xc0/0x130
>> [   16.490509]  virtnet_rq_alloc.isra.0+0xa4/0x1fc
>> [   16.510355]  try_fill_recv+0x2a4/0x584
>> [   16.526989]  virtnet_open+0xd4/0x238
>> [   16.542775]  __dev_open+0x110/0x24c
>> [   16.558280]  __dev_change_flags+0x194/0x20c
>> [   16.576879]  netif_change_flags+0x24/0x6c
>> [   16.594489]  dev_change_flags+0x48/0x7c
>> [   16.611462]  ip_auto_config+0x258/0x1114
>> [   16.628727]  do_one_initcall+0x80/0x1c8
>> [   16.645590]  kernel_init_freeable+0x208/0x2f0
>> [   16.664917]  kernel_init+0x24/0x1e0
>> [   16.680295]  ret_from_fork+0x10/0x20
>> [   16.696369] Code: 927cec03 cb0e0021 8b0e0042 a9411c26 (a900340c)
>> [   16.723106] ---[ end trace 0000000000000000 ]---
>> [   16.752866] Kernel panic - not syncing: Attempted to kill init!
>> exitcode=0x0000000b
>> [   16.792556] Kernel Offset: 0x3396ea200000 from 0xffff800080000000
>> [   16.818966] PHYS_OFFSET: 0xfff1000080000000
>> [   16.837237] CPU features: 0x0000000,00060005,13e38581,957e772f
>> [   16.862904] Memory Limit: none
>> [   16.876526] ---[ end Kernel panic - not syncing: Attempted to kill init!
>> exitcode=0x0000000b ]---
>>
>> This panic occurs because the swiotlb memory was previously shared to
>> the host (__set_memory_enc_dec()), which involves transitioning the
>> (large) leaf mappings to invalid, sharing to the host, then marking the
>> mappings valid again. But pageattr_p[mu]d_entry() would only update the
>> entry if it is a section mapping, since otherwise it concluded it must
>> be a table entry so shouldn't be modified. But p[mu]d_sect() only
>> returns true if the entry is valid. So the result was that the large
> 
> Maybe I missed something, pmd_sect() only checks PMD_TYPE_SECT, doesn't check
> PTE_VALID?
> Why it only returns true if the entry is valid?

PTE_VALID is bit 0.

#define PMD_TYPE_MASK		(_AT(pmdval_t, 3) << 0)
#define PMD_TYPE_TABLE		(_AT(pmdval_t, 3) << 0)
#define PMD_TYPE_SECT		(_AT(pmdval_t, 1) << 0)

So PMD_TYPE_TABLE and PMD_TYPE_SECT are both implicitly checking that PTE_VALID
is set.

> 
> #define pmd_sect(pmd)        ((pmd_val(pmd) & PMD_TYPE_MASK) == \
>                  PMD_TYPE_SECT)
> 

Thanks,
Ryan



^ permalink raw reply

* Re: [PATCH v1 1/3] arm64: mm: Fix rodata=full block mapping support for realm guests
From: Ryan Roberts @ 2026-03-25 17:29 UTC (permalink / raw)
  To: Yang Shi, Catalin Marinas, Will Deacon, David Hildenbrand (Arm),
	Dev Jain, Suzuki K Poulose, Jinjiang Tu, Kevin Brodsky
  Cc: linux-arm-kernel, linux-kernel, stable
In-Reply-To: <a3766dfc-06ed-4cdc-9c55-0dcc3638746e@os.amperecomputing.com>

On 23/03/2026 21:34, Yang Shi wrote:
> 
> 
> On 3/23/26 6:03 AM, Ryan Roberts wrote:
>> Commit a166563e7ec37 ("arm64: mm: support large block mapping when
>> rodata=full") enabled the linear map to be mapped by block/cont while
>> still allowing granular permission changes on BBML2_NOABORT systems by
>> lazily splitting the live mappings. This mechanism was intended to be
>> usable by realm guests since they need to dynamically share dma buffers
>> with the host by "decrypting" them - which for Arm CCA, means marking
>> them as shared in the page tables.
>>
>> However, it turns out that the mechanism was failing for realm guests
>> because realms need to share their dma buffers (via
>> __set_memory_enc_dec()) much earlier during boot than
>> split_kernel_leaf_mapping() was able to handle. The report linked below
>> showed that GIC's ITS was one such user. But during the investigation I
>> found other callsites that could not meet the
>> split_kernel_leaf_mapping() constraints.
>>
>> The problem is that we block map the linear map based on the boot CPU
>> supporting BBML2_NOABORT, then check that all the other CPUs support it
>> too when finalizing the caps. If they don't, then we stop_machine() and
>> split to ptes. For safety, split_kernel_leaf_mapping() previously
>> wouldn't permit splitting until after the caps were finalized. That
>> ensured that if any secondary cpus were running that didn't support
>> BBML2_NOABORT, we wouldn't risk breaking them.
>>
>> I've fix this problem by reducing the black-out window where we refuse
>> to split; there are now 2 windows. The first is from T0 until the page
>> allocator is inititialized. Splitting allocates memory for the page
>> allocator so it must be in use. The second covers the period between
>> starting to online the secondary cpus until the system caps are
>> finalized (this is a very small window).
>>
>> All of the problematic callers are calling __set_memory_enc_dec() before
>> the secondary cpus come online, so this solves the problem. However, one
>> of these callers, swiotlb_update_mem_attributes(), was trying to split
>> before the page allocator was initialized. So I have moved this call
>> from arch_mm_preinit() to mem_init(), which solves the ordering issue.
>>
>> I've added warnings and return an error if any attempt is made to split
>> in the black-out windows.
>>
>> Note there are other issues which prevent booting all the way to user
>> space, which will be fixed in subsequent patches.
> 
> Hi Ryan,
> 
> Thanks for putting everything to together to have the patches so quickly. It
> basically looks good to me. However, I'm thinking about whether we should have
> split_kernel_leaf_mapping() call for different memory allocators in different
> stages. If buddy has been initialized, it can call page allocator, otherwise,
> for example, in early boot stage, it can call memblock allocator. So
> split_kernel_leaf_mapping() should be able to be called anytime and we don't
> have to rely on the boot order of subsystems.

I considered that, but ultimately we would just be adding dead code. I've added
a warning that will catch this usage. So I'd prefer to leave it as is for now
and only add this functionality if we identify a need.

Thanks,
Ryan


> 
> Thanks,
> Yang
> 


^ permalink raw reply

* Re: [PATCH v5 09/10] clk: realtek: Add RTD1625-CRT clock controller driver
From: Philipp Zabel @ 2026-03-25 17:24 UTC (permalink / raw)
  To: Yu-Chun Lin, mturquette, sboyd, robh, krzk+dt, conor+dt, cylee12,
	afaerber, jyanchou
  Cc: devicetree, linux-clk, linux-kernel, linux-arm-kernel,
	linux-realtek-soc, james.tai, cy.huang, stanley_chang
In-Reply-To: <20260324025332.3416977-10-eleanor.lin@realtek.com>

On Di, 2026-03-24 at 10:53 +0800, Yu-Chun Lin wrote:
> From: Cheng-Yu Lee <cylee12@realtek.com>
> 
> Add support for the CRT (Clock, Reset, and Test) controller on the Realtek
> RTD1625 SoC. This driver provides clock and reset management for the
> system, allowing peripheral clients to request necessary resources for
> operation.
> 
> Signed-off-by: Cheng-Yu Lee <cylee12@realtek.com>
> Co-developed-by: Yu-Chun Lin <eleanor.lin@realtek.com>
> Signed-off-by: Yu-Chun Lin <eleanor.lin@realtek.com>
> ---
> Changes in v5:
> - Added '#include <dt-bindings/reset/realtek,rtd1625.h>'.
> - Replaced rtk_reset_bank array with rtk_reset_desc descriptor.
> - Implemented complete a mapping table for all reset IDs.
> ---
>  drivers/clk/realtek/Kconfig           |  14 +
>  drivers/clk/realtek/Makefile          |   1 +
>  drivers/clk/realtek/clk-rtd1625-crt.c | 913 ++++++++++++++++++++++++++
>  3 files changed, 928 insertions(+)
>  create mode 100644 drivers/clk/realtek/clk-rtd1625-crt.c
> 
[...]
> diff --git a/drivers/clk/realtek/clk-rtd1625-crt.c b/drivers/clk/realtek/clk-rtd1625-crt.c
> new file mode 100644
> index 000000000000..a56978aef83a
> --- /dev/null
> +++ b/drivers/clk/realtek/clk-rtd1625-crt.c
> @@ -0,0 +1,913 @@
[...]
> +static struct rtk_reset_desc rtd1625_crt_reset_descs[] = {
> +	/* Bank 0: offset 0x0 */
> +	[RTD1625_CRT_RSTN_MISC]         = { .ofs = 0x0, .bit = 0,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_DIP]          = { .ofs = 0x0, .bit = 2,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_GSPI]         = { .ofs = 0x0, .bit = 4,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_SDS]          = { .ofs = 0x0, .bit = 6,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_SDS_REG]      = { .ofs = 0x0, .bit = 8,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_SDS_PHY]      = { .ofs = 0x0, .bit = 10, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_GPU2D]        = { .ofs = 0x0, .bit = 12, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_DC_PHY]       = { .ofs = 0x0, .bit = 22, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_DCPHY_CRT]    = { .ofs = 0x0, .bit = 24, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_LSADC]        = { .ofs = 0x0, .bit = 26, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_SE]           = { .ofs = 0x0, .bit = 28, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_DLA]          = { .ofs = 0x0, .bit = 30, .write_en = 1 },
> +	/* Bank 1: offset 0x4 */
> +	[RTD1625_CRT_RSTN_JPEG]         = { .ofs = 0x4, .bit = 0,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_SD]           = { .ofs = 0x4, .bit = 2,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_SDIO]         = { .ofs = 0x4, .bit = 6,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCR_CNT]      = { .ofs = 0x4, .bit = 8,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE0_STITCH] = { .ofs = 0x4, .bit = 10, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE0_PHY]    = { .ofs = 0x4, .bit = 12, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE0]        = { .ofs = 0x4, .bit = 14, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE0_CORE]   = { .ofs = 0x4, .bit = 16, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE0_POWER]  = { .ofs = 0x4, .bit = 18, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE0_NONSTICH] = { .ofs = 0x4, .bit = 20, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE0_PHY_MDIO] = { .ofs = 0x4, .bit = 22, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE0_SGMII_MDIO] = { .ofs = 0x4, .bit = 24, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_VO2]          = { .ofs = 0x4, .bit = 28, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_MISC_SC0]     = { .ofs = 0x4, .bit = 30, .write_en = 1 },
> +	/* Bank 2: offset 0x8 */
> +	[RTD1625_CRT_RSTN_MD]           = { .ofs = 0x8, .bit = 4,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_LVDS1]        = { .ofs = 0x8, .bit = 6,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_LVDS2]        = { .ofs = 0x8, .bit = 8,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_MISC_SC1]     = { .ofs = 0x8, .bit = 10, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_I2C_3]        = { .ofs = 0x8, .bit = 12, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_FAN]          = { .ofs = 0x8, .bit = 14, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_TVE]          = { .ofs = 0x8, .bit = 16, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_AIO]          = { .ofs = 0x8, .bit = 18, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_VO]           = { .ofs = 0x8, .bit = 20, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_MIPI_CSI]     = { .ofs = 0x8, .bit = 22, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_HDMIRX]       = { .ofs = 0x8, .bit = 24, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_HDMIRX_WRAP]  = { .ofs = 0x8, .bit = 26, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_HDMI]         = { .ofs = 0x8, .bit = 28, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_DISP]         = { .ofs = 0x8, .bit = 30, .write_en = 1 },
> +	/* Bank 3: offset 0xc */
> +	[RTD1625_CRT_RSTN_SATA_PHY_POW1] = { .ofs = 0xc, .bit = 0,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_SATA_PHY_POW0] = { .ofs = 0xc, .bit = 2,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_SATA_MDIO1]   = { .ofs = 0xc, .bit = 4,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_SATA_MDIO0]   = { .ofs = 0xc, .bit = 6,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_SATA_WRAP]    = { .ofs = 0xc, .bit = 8,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_SATA_MAC_P1]  = { .ofs = 0xc, .bit = 10, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_SATA_MAC_P0]  = { .ofs = 0xc, .bit = 12, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_SATA_MAC_COM] = { .ofs = 0xc, .bit = 14, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE1_STITCH] = { .ofs = 0xc, .bit = 16, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE1_PHY]     = { .ofs = 0xc, .bit = 18, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE1]         = { .ofs = 0xc, .bit = 20, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE1_CORE]   = { .ofs = 0xc, .bit = 22, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE1_POWER]  = { .ofs = 0xc, .bit = 24, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE1_NONSTICH] = { .ofs = 0xc, .bit = 26, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE1_PHY_MDIO] = { .ofs = 0xc, .bit = 28, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_HDMITOP]      = { .ofs = 0xc, .bit = 30, .write_en = 1 },
> +	/* Bank 4: offset 0x68 */
> +	[RTD1625_CRT_RSTN_I2C_4]        = { .ofs = 0x68, .bit = 2,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_I2C_5]        = { .ofs = 0x68, .bit = 4,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_TSIO]         = { .ofs = 0x68, .bit = 6,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_VI]           = { .ofs = 0x68, .bit = 8,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_EDP]          = { .ofs = 0x68, .bit = 10, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_VE1_MMU]      = { .ofs = 0x68, .bit = 12, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_VE1_MMU_FUNC] = { .ofs = 0x68, .bit = 14, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_HSE_MMU]      = { .ofs = 0x68, .bit = 16, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_HSE_MMU_FUNC] = { .ofs = 0x68, .bit = 18, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_MDLM2M]       = { .ofs = 0x68, .bit = 20, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_ISO_GSPI]     = { .ofs = 0x68, .bit = 22, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_SOFT_NPU]     = { .ofs = 0x68, .bit = 24, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_SPI2EMMC]     = { .ofs = 0x68, .bit = 26, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_EARC]         = { .ofs = 0x68, .bit = 28, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_VE1]          = { .ofs = 0x68, .bit = 30, .write_en = 1 },
> +	/* Bank 5: offset 0x90 */
> +	[RTD1625_CRT_RSTN_PCIE2_STITCH]  = { .ofs = 0x90, .bit = 0,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE2_PHY]    = { .ofs = 0x90, .bit = 2,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE2]        = { .ofs = 0x90, .bit = 4,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE2_CORE]   = { .ofs = 0x90, .bit = 6,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE2_POWER]  = { .ofs = 0x90, .bit = 8,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE2_NONSTICH] = { .ofs = 0x90, .bit = 10, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE2_PHY_MDIO] = { .ofs = 0x90, .bit = 12, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_DCPHY_UMCTL2] = { .ofs = 0x90, .bit = 14, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_MIPI_DSI]     = { .ofs = 0x90, .bit = 16, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_HIFM]         = { .ofs = 0x90, .bit = 18, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_NSRAM]        = { .ofs = 0x90, .bit = 20, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_AUCPU0_REG]   = { .ofs = 0x90, .bit = 22, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_MDL_GENPW]    = { .ofs = 0x90, .bit = 24, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_MDL_CHIP]     = { .ofs = 0x90, .bit = 26, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_MDL_IP]       = { .ofs = 0x90, .bit = 28, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_TEST_MUX]     = { .ofs = 0x90, .bit = 30, .write_en = 1 },
> +	/* Bank 6: offset 0xb8 */
> +	[RTD1625_CRT_RSTN_ISO_BIST]     = { .ofs = 0xb8, .bit = 0,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_MAIN_BIST]    = { .ofs = 0xb8, .bit = 2,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_MAIN2_BIST]   = { .ofs = 0xb8, .bit = 4,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_VE1_BIST]     = { .ofs = 0xb8, .bit = 6,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_VE2_BIST]     = { .ofs = 0xb8, .bit = 8,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_DCPHY_BIST]   = { .ofs = 0xb8, .bit = 10, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_GPU_BIST]     = { .ofs = 0xb8, .bit = 12, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_DISP_BIST]    = { .ofs = 0xb8, .bit = 14, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_NPU_BIST]     = { .ofs = 0xb8, .bit = 16, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_CAS_BIST]     = { .ofs = 0xb8, .bit = 18, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_VE4_BIST]     = { .ofs = 0xb8, .bit = 20, .write_en = 1 },
> +	/* Bank 7: offset 0x454 (DUMMY0, no write_en) */
> +	[RTD1625_CRT_RSTN_EMMC]         = { .ofs = 0x454, .bit = 0 },
> +	/* Bank 8: offset 0x458 (DUMMY1, no write_en) */
> +	[RTD1625_CRT_RSTN_GPU]          = { .ofs = 0x458, .bit = 0 },
> +	/* Bank 9: offset 0x464 (DUMMY4, no write_en) */
> +	[RTD1625_CRT_RSTN_VE2]          = { .ofs = 0x464, .bit = 0 },
> +	/* Bank 10: offset 0x880 */
> +	[RTD1625_CRT_RSTN_UR1]          = { .ofs = 0x880, .bit = 0,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_UR2]          = { .ofs = 0x880, .bit = 2,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_UR3]          = { .ofs = 0x880, .bit = 4,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_UR4]          = { .ofs = 0x880, .bit = 6,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_UR5]          = { .ofs = 0x880, .bit = 8,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_UR6]          = { .ofs = 0x880, .bit = 10, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_UR7]          = { .ofs = 0x880, .bit = 12, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_UR8]          = { .ofs = 0x880, .bit = 14, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_UR9]          = { .ofs = 0x880, .bit = 16, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_UR_TOP]       = { .ofs = 0x880, .bit = 18, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_I2C_7]        = { .ofs = 0x880, .bit = 28, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_I2C_6]        = { .ofs = 0x880, .bit = 30, .write_en = 1 },
> +	/* Bank 11: offset 0x890 */
> +	[RTD1625_CRT_RSTN_SPI0]         = { .ofs = 0x890, .bit = 0,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_SPI1]         = { .ofs = 0x890, .bit = 2,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_SPI2]         = { .ofs = 0x890, .bit = 4,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_LSADC0]       = { .ofs = 0x890, .bit = 16, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_LSADC1]       = { .ofs = 0x890, .bit = 18, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_ISOMIS_DMA]   = { .ofs = 0x890, .bit = 20, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_AUDIO_ADC]    = { .ofs = 0x890, .bit = 22, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_DPTX]         = { .ofs = 0x890, .bit = 24, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_AUCPU1_REG]   = { .ofs = 0x890, .bit = 26, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_EDPTX]        = { .ofs = 0x890, .bit = 28, .write_en = 1 },
> +};

These should be moved into the reset driver. Then rtk_reset_desc
doesn't have to be a public interface between the clk and reset drivers
anymore.

regards
Philipp


^ permalink raw reply

* Re: [PATCH v5 03/10] reset: Add Realtek basic reset support
From: Philipp Zabel @ 2026-03-25 17:21 UTC (permalink / raw)
  To: Yu-Chun Lin, mturquette, sboyd, robh, krzk+dt, conor+dt, cylee12,
	afaerber, jyanchou
  Cc: devicetree, linux-clk, linux-kernel, linux-arm-kernel,
	linux-realtek-soc, james.tai, cy.huang, stanley_chang
In-Reply-To: <20260324025332.3416977-4-eleanor.lin@realtek.com>

On Di, 2026-03-24 at 10:53 +0800, Yu-Chun Lin wrote:
> From: Cheng-Yu Lee <cylee12@realtek.com>
> 
> Define the reset operations backed by a regmap-based register
> interface and prepare the reset controller to be registered
> through the reset framework.
> 
> Signed-off-by: Cheng-Yu Lee <cylee12@realtek.com>
> Co-developed-by: Yu-Chun Lin <eleanor.lin@realtek.com>
> Signed-off-by: Yu-Chun Lin <eleanor.lin@realtek.com>
> ---
> Changes in v5:
> - Created drivers/reset/realtek/ directory and include/linux/reset/realtek.h.
> - Extracted the common reset helpers:
>  - Moved the source code to drivers/reset/realtek/common.c and
>  - the header to include/linux/reset/realtek.h
> - Renamed rtk_reset_bank to rtk_reset_desc.
> - Added 'bits' member to rtk_reset_desc structure.
> - Removed rtk_reset_get_id() and rtk_reset_get_bank() helper.
> - Introduced rtk_reset_get_desc().
> ---
>  MAINTAINERS                    |  1 +
>  drivers/reset/Kconfig          |  1 +
>  drivers/reset/Makefile         |  1 +
>  drivers/reset/realtek/Kconfig  |  3 ++
>  drivers/reset/realtek/Makefile |  2 +
>  drivers/reset/realtek/common.c | 91 ++++++++++++++++++++++++++++++++++
>  include/linux/reset/realtek.h  | 25 ++++++++++
>  7 files changed, 124 insertions(+)
>  create mode 100644 drivers/reset/realtek/Kconfig
>  create mode 100644 drivers/reset/realtek/Makefile
>  create mode 100644 drivers/reset/realtek/common.c
>  create mode 100644 include/linux/reset/realtek.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 721356d4c02c..9419b0497e0b 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -22229,6 +22229,7 @@ L:	devicetree@vger.kernel.org
>  L:	linux-clk@vger.kernel.org
>  S:	Supported
>  F:	Documentation/devicetree/bindings/clock/realtek*
> +F:	drivers/reset/realtek/*
>  F:	include/dt-bindings/clock/realtek*
>  
>  REALTEK SPI-NAND
> diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
> index 7ce151f6a7e4..03be1931f264 100644
> --- a/drivers/reset/Kconfig
> +++ b/drivers/reset/Kconfig
> @@ -398,6 +398,7 @@ config RESET_ZYNQMP
>  
>  source "drivers/reset/amlogic/Kconfig"
>  source "drivers/reset/hisilicon/Kconfig"
> +source "drivers/reset/realtek/Kconfig"
>  source "drivers/reset/spacemit/Kconfig"
>  source "drivers/reset/starfive/Kconfig"
>  source "drivers/reset/sti/Kconfig"
> diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
> index fc0cc99f8514..4407d1630070 100644
> --- a/drivers/reset/Makefile
> +++ b/drivers/reset/Makefile
> @@ -2,6 +2,7 @@
>  obj-y += core.o
>  obj-y += amlogic/
>  obj-y += hisilicon/
> +obj-y += realtek/
>  obj-y += spacemit/
>  obj-y += starfive/
>  obj-y += sti/
> diff --git a/drivers/reset/realtek/Kconfig b/drivers/reset/realtek/Kconfig
> new file mode 100644
> index 000000000000..99a14d355803
> --- /dev/null
> +++ b/drivers/reset/realtek/Kconfig
> @@ -0,0 +1,3 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +config RESET_RTK_COMMON
> +	bool
> diff --git a/drivers/reset/realtek/Makefile b/drivers/reset/realtek/Makefile
> new file mode 100644
> index 000000000000..b59a3f7f2453
> --- /dev/null
> +++ b/drivers/reset/realtek/Makefile
> @@ -0,0 +1,2 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +obj-$(CONFIG_RESET_RTK_COMMON) += common.o
> diff --git a/drivers/reset/realtek/common.c b/drivers/reset/realtek/common.c
> new file mode 100644
> index 000000000000..b9e3219dc8f7
> --- /dev/null
> +++ b/drivers/reset/realtek/common.c
> @@ -0,0 +1,91 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2019 Realtek Semiconductor Corporation
> + */
> +
> +#include <linux/device.h>
> +#include <linux/of.h>
> +#include <linux/regmap.h>
> +#include <linux/reset-controller.h>
> +#include <linux/reset/realtek.h>
> +
> +struct rtk_reset_data {
> +	struct reset_controller_dev rcdev;
> +	struct rtk_reset_desc *descs;
> +	struct regmap *regmap;
> +};
> +
> +static inline struct rtk_reset_data *to_rtk_reset_controller(struct reset_controller_dev *r)
> +{
> +	return container_of(r, struct rtk_reset_data, rcdev);
> +}
> +
> +static inline struct rtk_reset_desc *rtk_reset_get_desc(struct rtk_reset_data *data,
> +							unsigned long idx)
> +{
> +	return &data->descs[idx];
> +}
> +
> +static int rtk_reset_assert(struct reset_controller_dev *rcdev,
> +			    unsigned long idx)
> +{
> +	struct rtk_reset_data *data = to_rtk_reset_controller(rcdev);
> +	struct rtk_reset_desc *desc = rtk_reset_get_desc(data, idx);
> +	u32 mask = desc->write_en ? (0x3 << desc->bit) : BIT(desc->bit);
> +	u32 val  = desc->write_en ? (0x2 << desc->bit) : 0;
> +
> +	return regmap_update_bits(data->regmap, desc->ofs, mask, val);
> +}
> +
> +static int rtk_reset_deassert(struct reset_controller_dev *rcdev,
> +			      unsigned long idx)
> +{
> +	struct rtk_reset_data *data = to_rtk_reset_controller(rcdev);
> +	struct rtk_reset_desc *desc = rtk_reset_get_desc(data, idx);
> +	u32 mask = desc->write_en ? (0x3 << desc->bit) : BIT(desc->bit);
> +	u32 val  = mask;
> +
> +	return regmap_update_bits(data->regmap, desc->ofs, mask, val);
> +}
> +
> +static int rtk_reset_status(struct reset_controller_dev *rcdev,
> +			    unsigned long idx)
> +{
> +	struct rtk_reset_data *data = to_rtk_reset_controller(rcdev);
> +	struct rtk_reset_desc *desc = rtk_reset_get_desc(data, idx);
> +	u32 val;
> +	int ret;
> +
> +	ret = regmap_read(data->regmap, desc->ofs, &val);
> +	if (ret)
> +		return ret;
> +
> +	return !((val >> desc->bit) & 1);
> +}
> +
> +static const struct reset_control_ops rtk_reset_ops = {
> +	.assert   = rtk_reset_assert,
> +	.deassert = rtk_reset_deassert,
> +	.status   = rtk_reset_status,
> +};
> +
> +int rtk_reset_controller_add(struct device *dev,
> +			     struct rtk_reset_initdata *initdata)
> +{
> +	struct rtk_reset_data *data;
> +
> +	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
> +	if (!data)
> +		return -ENOMEM;
> +
> +	data->regmap          = initdata->regmap;
> +	data->descs           = initdata->descs;
> +	data->rcdev.owner     = THIS_MODULE;
> +	data->rcdev.ops       = &rtk_reset_ops;
> +	data->rcdev.dev       = dev;
> +	data->rcdev.of_node   = dev->of_node;
> +	data->rcdev.nr_resets = initdata->num_descs;
> +
> +	return devm_reset_controller_register(dev, &data->rcdev);
> +}
> +EXPORT_SYMBOL_GPL(rtk_reset_controller_add);

Please implement this as an auxiliary device driver. Move the
rtk_reset_initdata definitions in here and select them based on either
auxiliary_device_id (see imx8mp-audiomix or spacemit) or of_device_id
(see eyeq).
The regmap can be retrieved from the parent (clk device) via
dev_get_regmap (see imx8mp-audiomix).

> diff --git a/include/linux/reset/realtek.h b/include/linux/reset/realtek.h
> new file mode 100644
> index 000000000000..3c2226e3ed26
> --- /dev/null
> +++ b/include/linux/reset/realtek.h
> @@ -0,0 +1,25 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef __LINUX_RESET_REALTEK_H__
> +#define __LINUX_RESET_REALTEK_H__
> +
> +#include <linux/types.h>
> +
> +struct device;
> +struct regmap;
> +
> +struct rtk_reset_desc {
> +	u32 ofs;
> +	u32 bit;
> +	u32 write_en;
> +};
> +
> +struct rtk_reset_initdata {
> +	struct rtk_reset_desc *descs;
> +	u32 num_descs;
> +	struct regmap *regmap;
> +};
> +
> +int rtk_reset_controller_add(struct device *dev,
> +			     struct rtk_reset_initdata *initdata);
> +
> +#endif /* __LINUX_RESET_REALTEK_H__ */

With the above suggested changes, this header is not necessary.

regards
Philipp


^ permalink raw reply

* Re: [PATCH] i2c: s3c24xx: check the size of the SMBUS message before using it
From: Andi Shyti @ 2026-03-25 17:17 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-arm-kernel, linux-samsung-soc, linux-i2c, linux-kernel,
	Krzysztof Kozlowski, Alim Akhtar, stable
In-Reply-To: <2026022314-rely-scrubbed-4839@gregkh>

Hi Greg,

On Mon, Feb 23, 2026 at 06:05:15PM +0100, Greg Kroah-Hartman wrote:
> The first byte of an i2c SMBUS message is the size, and it should be
> verified to ensure that it is in the range of 0..I2C_SMBUS_BLOCK_MAX
> before processing it.
> 
> This is the same logic that was added in commit a6e04f05ce0b ("i2c:
> tegra: check msg length in SMBUS block read") to the i2c tegra driver.
> 
> Cc: Krzysztof Kozlowski <krzk@kernel.org>
> Cc: Alim Akhtar <alim.akhtar@samsung.com>
> Cc: Andi Shyti <andi.shyti@kernel.org>
> Cc: stable <stable@kernel.org>
> Assisted-by: gkh_clanker_2000
> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

merged to i2c/i2c-host.

Thanks,
Andi


^ permalink raw reply

* Re: [PATCH v4 8/9] dt-bindings: net: wireless: brcm: Add compatible for bcm43752
From: Rob Herring @ 2026-03-25 17:09 UTC (permalink / raw)
  To: Ronald Claveau
  Cc: Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
	Krzysztof Kozlowski, Conor Dooley, Ulf Hansson, Johannes Berg,
	van Spriel, linux-arm-kernel, linux-amlogic, devicetree,
	linux-kernel, linux-mmc, linux-wireless
In-Reply-To: <20260325-add-emmc-t7-vim4-v4-8-44c7b4a5e459@aliel.fr>

On Wed, Mar 25, 2026 at 10:15:26AM +0100, Ronald Claveau wrote:
> Add bcm43752 compatible with its bcm4329 compatible fallback.
> 
> Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>

Missing Conor's ack.

> ---
>  Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml b/Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml
> index 3be7576787644..81fd3e37452a6 100644
> --- a/Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml
> +++ b/Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml
> @@ -42,6 +42,7 @@ properties:
>                - brcm,bcm4356-fmac
>                - brcm,bcm4359-fmac
>                - brcm,bcm4366-fmac
> +              - brcm,bcm43752-fmac
>                - cypress,cyw4373-fmac
>                - cypress,cyw43012-fmac
>                - infineon,cyw43439-fmac
> 
> -- 
> 2.49.0
> 


^ permalink raw reply

* Re: [PATCH v2] ARM: dts: imx: Add DT overlays for DH i.MX6 DHCOM SoM and boards
From: Frank Li @ 2026-03-25 17:02 UTC (permalink / raw)
  To: linux-arm-kernel, Marek Vasut
  Cc: Frank Li, Christoph Niedermaier, Conor Dooley, Fabio Estevam,
	Krzysztof Kozlowski, Pengutronix Kernel Team, Rob Herring,
	Sascha Hauer, devicetree, imx, kernel, linux-kernel
In-Reply-To: <20260324190356.74293-1-marex@nabladev.com>


On Tue, 24 Mar 2026 20:03:11 +0100, Marek Vasut wrote:
> Add DT overlays to support DH i.MX6 DHCOM SoM carrier board expansion
> modules. The following DT overlays are implemented:
> - PDK2:
>   - DH 497-200 Display board in edge connector X12
>   - DH 505-200 Display board in edge connector X12
>   - DH 531-100 SPI/I2C board in header X21
>   - DH 531-200 SPI/I2C board in header X22
>   - DH 560-200 Display board in edge connector X12
> - PicoITX:
>   - DH 626-100 Display board in edge connector X2
>
> [...]

Applied, thanks!

[1/1] ARM: dts: imx: Add DT overlays for DH i.MX6 DHCOM SoM and boards
      commit: 7bc76d413dbe6631a207b38aa67b2d00fdc27b2c

move status = "okay" to last property.

Best regards,
--
Frank Li <Frank.Li@nxp.com>


^ permalink raw reply

* Re: [PATCH v3 0/7] arm64: dts: imx943: various update
From: Frank Li @ 2026-03-25 16:55 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, Peng Fan (OSS)
  Cc: Frank Li, devicetree, imx, linux-arm-kernel, linux-kernel,
	Peng Fan, Ranjani Vaidyanathan, Joy Zou, Florin Leotescu
In-Reply-To: <20260324-imx943-dts-v1-v3-0-b33bf1f1c254@nxp.com>


On Tue, 24 Mar 2026 13:44:06 +0800, Peng Fan (OSS) wrote:
> Update pin header
> Add V2X/ELE mailbox nodes, more SCMI nodes, thermal nodes, fan node
> Add nxp,ctrl-ids.
>
>

Applied, thanks!

[1/7] arm64: dts: imx94: Update pin headers
      commit: 91faaca1db2ff31dd9a964c419ea39dcb396022f
[2/7] arm64: dts: imx94: Add V2X/ELE mailbox nodes
      commit: 87ac991725ccc441af0fc16d54f9cee7e05bd4a2
[3/7] arm64: dts: imx94: Add SCMI sensor/lmm/cpu nodes
      commit: dee18abd657f2cf5c1540eafadfdeb9444f4721d
[4/7] arm64: dts: imx943: Add thermal support
      commit: 81b428c2a761d9f40fb95eb0c556544541988263
[5/7] arm64: dts: imx943-evk: Add nxp,ctrl-ids for scmi_misc
      commit: a2cdee4ce35863e0e6d4f58808f8e051b9608073
[6/7] arm64: dts: imx943-evk: Add fan node and enable active cooling on A55
      commit: 12cac5ae8bc741de9b03a2c23d128bfaf0c4c4ce

Adjust pwm@2f after codec@1a keep order by address

[7/7] arm64: dts: imx943-evk: Add pf09/53 thermal zone
      commit: bd25e888974ffa2e6097b2ee352c8f6f860f5e87

Add extra empty line between children node trips and properties.

Best regards,
--
Frank Li <Frank.Li@nxp.com>


^ permalink raw reply

* Re: [PATCH RESEND 1/2] regulator: dt-bindings: mt6315: Add regulator supplies
From: Mark Brown @ 2026-03-25 16:55 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Chen-Yu Tsai, Liam Girdwood, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Matthias Brugger, AngeloGioacchino Del Regno,
	linux-arm-kernel, linux-mediatek, devicetree
In-Reply-To: <20260325-uncovered-carp-of-inquire-8a7acf@quoll>

[-- Attachment #1: Type: text/plain, Size: 792 bytes --]

On Wed, Mar 25, 2026 at 09:56:00AM +0100, Krzysztof Kozlowski wrote:
> On Tue, Mar 24, 2026 at 01:30:28PM +0800, Chen-Yu Tsai wrote:

> > +      pvdd4-supply:
> > +        description: Supply for vbuck4

> These all look per-regulator supplies, so I think they should be in each
> regulator node (see also regulator.yaml).

> Or in top-level, but not in "regulators" node. The regulators is only
> wrapping node for children.

> I wonder what should be our preference - have supplies per regulator or
> in top-level node. @Mark, any preference from your side?

The top level, so people can figure out where to describe supplies
without having to read the bindings so much - the supplies go into the
chip, even if they're distributed within it.

Please don't add random characters to my name.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* Re: [PATCH v27 2/4] dt-bindings: i2c: ast2600-i2c.yaml: Add global-regs and transfer-mode properties
From: Rob Herring @ 2026-03-25 16:52 UTC (permalink / raw)
  To: Ryan Chen
  Cc: Jeremy Kerr, andriy.shevchenko@linux.intel.com, Andi Shyti,
	Krzysztof Kozlowski, Conor Dooley, Joel Stanley, Andrew Jeffery,
	Benjamin Herrenschmidt, Rayn Chen, Philipp Zabel,
	linux-i2c@vger.kernel.org, devicetree@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-aspeed@lists.ozlabs.org, linux-kernel@vger.kernel.org,
	openbmc@lists.ozlabs.org
In-Reply-To: <TY2PPF5CB9A1BE6F0B9087048F46ABD72A6F249A@TY2PPF5CB9A1BE6.apcprd06.prod.outlook.com>

On Wed, Mar 25, 2026 at 08:11:54AM +0000, Ryan Chen wrote:
> Hello Jeremy,
> 	Thanks the review.
> 
> > Subject: Re: [PATCH v27 2/4] dt-bindings: i2c: ast2600-i2c.yaml: Add global-regs
> > and transfer-mode properties
> > 
> > Hi Ryan,
> > 
> > > The AST2600 I2C controller supports three transfer modes (byte,
> > > buffer, DMA). Add "aspeed,transfer-mode" so DT can select the
> > > preferred transfer method per controller instance.
> > 
> > This patch does not add an aspeed,transfer-mode property.
> Will update use aspeed,enable-dma

[...]

> > > +  aspeed,enable-dma:
> > > +    type: boolean
> > > +    description: |
> > > +      I2C bus enable dma mode transfer.
> > > +
> > > +      ASPEED ast2600 platform equipped with 16 I2C controllers that
> > > +share a
> > > +      single DMA engine. DTS files can specify the data transfer mode
> > > +to/from
> > > +      the device, either DMA or programmed I/O.
> > 
> > As we had discussed: this does not define the transfer mode, only whether
> > DMA is available to the peripheral.
> > 
> > Why mention the 16 i2c controllers here?
> > 
> > Please keep this description simple and relevant to the specific purpose of the
> > property.
> 
> Will update with following.
> description: Enable DMA for transfers on this I2C bus.

You still don't understand the distinction. It's not enable, but that 
the h/w instance *has* DMA capability or not. It is still up to the OS 
what to do with that information.

Rob


^ permalink raw reply

* Re: [PATCH v13 3/6] iommu: Add verisilicon IOMMU driver
From: Will Deacon @ 2026-03-25 16:36 UTC (permalink / raw)
  To: Benjamin Gaignard
  Cc: joro, robin.murphy, robh, krzk+dt, conor+dt, heiko,
	nicolas.dufresne, p.zabel, mchehab, iommu, devicetree,
	linux-kernel, linux-arm-kernel, linux-rockchip, linux-media
In-Reply-To: <e083e933-2746-4b26-ac33-3b32d362b28e@collabora.com>

On Tue, Mar 24, 2026 at 05:28:44PM +0100, Benjamin Gaignard wrote:
> 
> Le 24/03/2026 à 16:46, Will Deacon a écrit :
> > On Mon, Feb 16, 2026 at 10:51:35AM +0100, Benjamin Gaignard wrote:
> > > The Verisilicon IOMMU hardware block can be found in combination
> > > with Verisilicon hardware video codecs (encoders or decoders) on
> > > different SoCs.
> > > Enable it will allow us to use non contiguous memory allocators
> > > for Verisilicon video codecs.
> > > If both decoder and this iommu driver are compiled has modules
> > > there is undefined symboles issues so this iommu driver could
> > > only be compiled has built-in.
> > > 
> > > Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
> > > ---
> > >   MAINTAINERS               |   8 +
> > >   drivers/iommu/Kconfig     |  11 +
> > >   drivers/iommu/Makefile    |   1 +
> > >   drivers/iommu/vsi-iommu.c | 794 ++++++++++++++++++++++++++++++++++++++
> > >   include/linux/vsi-iommu.h |  21 +
> > >   5 files changed, 835 insertions(+)
> > >   create mode 100644 drivers/iommu/vsi-iommu.c
> > >   create mode 100644 include/linux/vsi-iommu.h
> > [...]
> > 
> > > +static size_t vsi_iommu_unmap(struct iommu_domain *domain, unsigned long _iova,
> > > +			      size_t size, size_t count, struct iommu_iotlb_gather *gather)
> > > +{
> > > +	struct vsi_iommu_domain *vsi_domain = to_vsi_domain(domain);
> > > +	dma_addr_t pte_dma, iova = (dma_addr_t)_iova;
> > > +	unsigned long flags;
> > > +	phys_addr_t pt_phys;
> > > +	u32 dte;
> > > +	u32 *pte_addr;
> > > +	size_t unmap_size = 0;
> > > +
> > > +	spin_lock_irqsave(&vsi_domain->lock, flags);
> > > +
> > > +	dte = vsi_domain->dt[vsi_iova_dte_index(iova)];
> > > +	/* Just return 0 if iova is unmapped */
> > > +	if (!vsi_dte_is_pt_valid(dte))
> > > +		goto unlock;
> > > +
> > > +	pt_phys = vsi_dte_pt_address(dte);
> > > +	pte_addr = (u32 *)phys_to_virt(pt_phys) + vsi_iova_pte_index(iova);
> > > +	pte_dma = pt_phys + vsi_iova_pte_index(iova) * sizeof(u32);
> > > +	unmap_size = vsi_iommu_unmap_iova(vsi_domain, pte_addr, pte_dma, size);
> > > +
> > > +unlock:
> > > +	spin_unlock_irqrestore(&vsi_domain->lock, flags);
> > > +
> > > +	return unmap_size;
> > > +}
> > I still think you need TLB invalidation here.
> > 
> > I looked at the downstream code that you linked to and it litters the
> > invalidation in the callers via mpp_iommu_flush_tlb(), which tend to
> > invalidate _before_ starting an operation. That's very likely buggy and
> > certainly not something we want upstream.
> > 
> > The unmap routine should do the invalidation so that, when it returns,
> > the pages really are unmapped from the device (assuming strict mode).
> > 
> > I know you said that you tried to add invalidation here and it "didn't
> > work", but that's not something I can really help you with.
> 
> I know you expect the hardware to work like that but that isn't not the
> case.

The hardware appears to have a register to invalidate the entire TLB.
We can use that if there's nothing else.

> I spend quite long to try to found hidden bit(s) or an other way to do like
> you want but I can't find any solution.

Then we can invalidate the entire TLB.

> As you mention the downstream code suggest that the iommu can't invalidate
> TLB in unmap routine so I don't see how to progress.

The downstream code is a tangled mess; I don't think it suggests anything
about what the IOMMU hardware is capable of.

> Maybe we should just admit that is how the hardware work.

No.

The upstream kernel isn't a dumping ground for vendor crap. The hardware
has TLB invalidation functionality and so we should use it. If we don't,
then we're not giving the IOMMU API what it expects and any callers
outside of the video codecs will be landed with problems when unmap
doesn't work as expected.

> This v13 has fixed the documentation so I don't plan to spend more time on this driver.

That's a shame, I'm really not asking for much.

Will


^ permalink raw reply

* Re: [PATCH v3] arm64: dts: imx8mp-frdm: add sd, ethernet, wifi, usb and hdmi support
From: Frank Li @ 2026-03-25 16:35 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, Fabian Pfitzner
  Cc: Frank Li, devicetree, imx, linux-arm-kernel, linux-kernel
In-Reply-To: <20260325-fpf-imx8mp-frdm-v3-1-1c98eade991a@pengutronix.de>


On Wed, 25 Mar 2026 17:01:49 +0100, Fabian Pfitzner wrote:
> Add support for the following new features:
>
> - SD Card
> - Ethernet (FEC + EQOS)
> - Wifi
> - USB
> - HDMI
>
> [...]

Applied, thanks!

[1/1] arm64: dts: imx8mp-frdm: add sd, ethernet, wifi, usb and hdmi support
      commit: 961719c5456ce407221868d9cab2a1311ccf1eeb

Remove extra line before &hdmi_pvi
move usb* node before usdhc1 to keep alphabet order.


Best regards,
--
Frank Li <Frank.Li@nxp.com>


^ permalink raw reply

* [PATCH 1/1] clk: scmi: Add error message if SCMI protocol handler could not be found
From: Alexander Stein @ 2026-03-25 16:35 UTC (permalink / raw)
  To: Sudeep Holla, Cristian Marussi, Michael Turquette, Stephen Boyd
  Cc: Alexander Stein, arm-scmi, linux-arm-kernel, linux-clk,
	linux-kernel

In case the protocol could not be found an error message is better than
probe just failing with error code -22.

Signed-off-by: Alexander Stein <alexander.stein@ew.tq-group.com>
---
 drivers/clk/clk-scmi.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/clk-scmi.c b/drivers/clk/clk-scmi.c
index 7c562559ad8bb..c32b15b272ccd 100644
--- a/drivers/clk/clk-scmi.c
+++ b/drivers/clk/clk-scmi.c
@@ -384,7 +384,8 @@ static int scmi_clocks_probe(struct scmi_device *sdev)
 	scmi_proto_clk_ops =
 		handle->devm_protocol_get(sdev, SCMI_PROTOCOL_CLOCK, &ph);
 	if (IS_ERR(scmi_proto_clk_ops))
-		return PTR_ERR(scmi_proto_clk_ops);
+		return dev_err_probe(dev, PTR_ERR(scmi_proto_clk_ops),
+				     "No SCMI protocol handler found\n");
 
 	count = scmi_proto_clk_ops->count_get(ph);
 	if (count < 0) {
-- 
2.43.0



^ permalink raw reply related

* Re: [PATCH] arm64: panic if IRQ shadow call stack allocation fails
From: Will Deacon @ 2026-03-25 16:35 UTC (permalink / raw)
  To: Osama Abdelkader
  Cc: Catalin Marinas, Mark Rutland, Ard Biesheuvel, Breno Leitao,
	Ryo Takakura, linux-arm-kernel, linux-kernel
In-Reply-To: <20260324161545.5441-1-osama.abdelkader@gmail.com>

On Tue, Mar 24, 2026 at 05:15:41PM +0100, Osama Abdelkader wrote:
> diff --git a/arch/arm64/kernel/irq.c b/arch/arm64/kernel/irq.c
> index 15dedb385b9e..b32ed7ef8e00 100644
> --- a/arch/arm64/kernel/irq.c
> +++ b/arch/arm64/kernel/irq.c
> @@ -14,6 +14,7 @@
>  #include <linux/init.h>
>  #include <linux/irq.h>
>  #include <linux/irqchip.h>
> +#include <linux/kernel.h>
>  #include <linux/kprobes.h>
>  #include <linux/memory.h>
>  #include <linux/scs.h>
> @@ -32,23 +33,26 @@ DEFINE_PER_CPU(struct nmi_ctx, nmi_contexts);
>  
>  DEFINE_PER_CPU(unsigned long *, irq_stack_ptr);
>  
> -
>  DECLARE_PER_CPU(unsigned long *, irq_shadow_call_stack_ptr);
>  
>  #ifdef CONFIG_SHADOW_CALL_STACK
>  DEFINE_PER_CPU(unsigned long *, irq_shadow_call_stack_ptr);
>  #endif
>  
> -static void init_irq_scs(void)
> +static void __init init_irq_scs(void)
>  {
>  	int cpu;
> +	void *s;
>  
>  	if (!scs_is_enabled())
>  		return;
>  
> -	for_each_possible_cpu(cpu)
> -		per_cpu(irq_shadow_call_stack_ptr, cpu) =
> -			scs_alloc(early_cpu_to_node(cpu));
> +	for_each_possible_cpu(cpu) {
> +		s = scs_alloc(early_cpu_to_node(cpu));
> +		if (!s)
> +			panic("irq: Failed to allocate shadow call stack\n");
> +		per_cpu(irq_shadow_call_stack_ptr, cpu) = s;
> +	}

I don't especially see the point in these panic() messages given that
presumably all sorts of other things will go wrong if we fail simple
allocations this early during boot.

If you really want to check this, then we should at least do the same
for the IRQ stack itself, otherwise it's all a bit academic. So maybe
have init_irq_scs() and init_irq_stacks() return -ENOMEM so that
init_IRQ() can panic?

Will


^ permalink raw reply

* Re: [PATCH v2 2/3] KVM: arm64: Disable SPE Profiling Buffer when running in guest context
From: Alexandru Elisei @ 2026-03-25 16:34 UTC (permalink / raw)
  To: Will Deacon
  Cc: kvmarm, mark.rutland, linux-arm-kernel, Marc Zyngier,
	Oliver Upton, James Clark, Leo Yan, Suzuki K Poulose, Fuad Tabba,
	Yabin Cui
In-Reply-To: <20260227212136.7660-3-will@kernel.org>

Hi Will,

The patch looks good to me:

Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>

Also tested the series for about 24h on an Orion O6 board with SPE enabled by
profiling two host processes spread across all CPUs with SPE, and at the same
time profiling a virtual machine with the VCPUs simiarly spread across the CPUs
with SPE:

Tested-by: Alexandru Elisei <alexandru.elisei@arm.com>

Thanks,
Alex

On Fri, Feb 27, 2026 at 09:21:34PM +0000, Will Deacon wrote:
> The nVHE world-switch code relies on zeroing PMSCR_EL1 to disable
> profiling data generation in guest context when SPE is in use by the
> host.
> 
> Unfortunately, this may leave PMBLIMITR_EL1.E set and consequently we
> can end up running in guest/hypervisor context with the Profiling Buffer
> enabled. The current "known issues" document for Rev M.a of the Arm ARM
> states that this can lead to speculative, out-of-context translations:
> 
>   | 2.18 D23136:
>   |
>   | When the Profiling Buffer is enabled, profiling is not stopped, and
>   | Discard mode is not enabled, the Statistical Profiling Unit might
>   | cause speculative translations for the owning translation regime,
>   | including when the owning translation regime is out-of-context.
> 
> In a similar fashion to TRBE, ensure that the Profiling Buffer is
> disabled during the nVHE world switch before we start messing with the
> stage-2 MMU and trap configuration.
> 
> Cc: Marc Zyngier <maz@kernel.org>
> Cc: Oliver Upton <oupton@kernel.org>
> Cc: James Clark <james.clark@linaro.org>
> Cc: Leo Yan <leo.yan@arm.com>
> Cc: Suzuki K Poulose <suzuki.poulose@arm.com>
> Cc: Fuad Tabba <tabba@google.com>
> Cc: Alexandru Elisei <alexandru.elisei@arm.com>
> Fixes: f85279b4bd48 ("arm64: KVM: Save/restore the host SPE state when entering/leaving a VM")
> Signed-off-by: Will Deacon <will@kernel.org>
> ---
>  arch/arm64/include/asm/kvm_host.h  |  1 +
>  arch/arm64/kvm/hyp/nvhe/debug-sr.c | 33 ++++++++++++++++++++----------
>  arch/arm64/kvm/hyp/nvhe/switch.c   |  2 +-
>  3 files changed, 24 insertions(+), 12 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index 1532ad2b2ec2..d527c77977dd 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -768,6 +768,7 @@ struct kvm_host_data {
>  		struct kvm_guest_debug_arch regs;
>  		/* Statistical profiling extension */
>  		u64 pmscr_el1;
> +		u64 pmblimitr_el1;
>  		/* Self-hosted trace */
>  		u64 trfcr_el1;
>  		u64 trblimitr_el1;
> diff --git a/arch/arm64/kvm/hyp/nvhe/debug-sr.c b/arch/arm64/kvm/hyp/nvhe/debug-sr.c
> index 3dbdee1148d3..75158a9cd06a 100644
> --- a/arch/arm64/kvm/hyp/nvhe/debug-sr.c
> +++ b/arch/arm64/kvm/hyp/nvhe/debug-sr.c
> @@ -14,20 +14,20 @@
>  #include <asm/kvm_hyp.h>
>  #include <asm/kvm_mmu.h>
>  
> -static void __debug_save_spe(u64 *pmscr_el1)
> +static void __debug_save_spe(void)
>  {
> -	u64 reg;
> +	u64 *pmscr_el1, *pmblimitr_el1;
>  
> -	/* Clear pmscr in case of early return */
> -	*pmscr_el1 = 0;
> +	pmscr_el1 = host_data_ptr(host_debug_state.pmscr_el1);
> +	pmblimitr_el1 = host_data_ptr(host_debug_state.pmblimitr_el1);
>  
>  	/*
>  	 * At this point, we know that this CPU implements
>  	 * SPE and is available to the host.
>  	 * Check if the host is actually using it ?
>  	 */
> -	reg = read_sysreg_s(SYS_PMBLIMITR_EL1);
> -	if (!(reg & BIT(PMBLIMITR_EL1_E_SHIFT)))
> +	*pmblimitr_el1 = read_sysreg_s(SYS_PMBLIMITR_EL1);
> +	if (!(*pmblimitr_el1 & BIT(PMBLIMITR_EL1_E_SHIFT)))
>  		return;
>  
>  	/* Yes; save the control register and disable data generation */
> @@ -37,18 +37,29 @@ static void __debug_save_spe(u64 *pmscr_el1)
>  
>  	/* Now drain all buffered data to memory */
>  	psb_csync();
> +	dsb(nsh);
> +
> +	/* And disable the profiling buffer */
> +	write_sysreg_s(0, SYS_PMBLIMITR_EL1);
> +	isb();
>  }
>  
> -static void __debug_restore_spe(u64 pmscr_el1)
> +static void __debug_restore_spe(void)
>  {
> -	if (!pmscr_el1)
> +	u64 pmblimitr_el1 = *host_data_ptr(host_debug_state.pmblimitr_el1);
> +
> +	if (!(pmblimitr_el1 & BIT(PMBLIMITR_EL1_E_SHIFT)))
>  		return;
>  
>  	/* The host page table is installed, but not yet synchronised */
>  	isb();
>  
> +	/* Re-enable the profiling buffer. */
> +	write_sysreg_s(pmblimitr_el1, SYS_PMBLIMITR_EL1);
> +	isb();
> +
>  	/* Re-enable data generation */
> -	write_sysreg_el1(pmscr_el1, SYS_PMSCR);
> +	write_sysreg_el1(*host_data_ptr(host_debug_state.pmscr_el1), SYS_PMSCR);
>  }
>  
>  static void __trace_do_switch(u64 *saved_trfcr, u64 new_trfcr)
> @@ -177,7 +188,7 @@ void __debug_save_host_buffers_nvhe(struct kvm_vcpu *vcpu)
>  {
>  	/* Disable and flush SPE data generation */
>  	if (host_data_test_flag(HAS_SPE))
> -		__debug_save_spe(host_data_ptr(host_debug_state.pmscr_el1));
> +		__debug_save_spe();
>  
>  	/* Disable BRBE branch records */
>  	if (host_data_test_flag(HAS_BRBE))
> @@ -195,7 +206,7 @@ void __debug_switch_to_guest(struct kvm_vcpu *vcpu)
>  void __debug_restore_host_buffers_nvhe(struct kvm_vcpu *vcpu)
>  {
>  	if (host_data_test_flag(HAS_SPE))
> -		__debug_restore_spe(*host_data_ptr(host_debug_state.pmscr_el1));
> +		__debug_restore_spe();
>  	if (host_data_test_flag(HAS_BRBE))
>  		__debug_restore_brbe(*host_data_ptr(host_debug_state.brbcr_el1));
>  	if (__trace_needs_switch())
> diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c
> index f00688e69d88..9b6e87dac3b9 100644
> --- a/arch/arm64/kvm/hyp/nvhe/switch.c
> +++ b/arch/arm64/kvm/hyp/nvhe/switch.c
> @@ -278,7 +278,7 @@ int __kvm_vcpu_run(struct kvm_vcpu *vcpu)
>  	 * We're about to restore some new MMU state. Make sure
>  	 * ongoing page-table walks that have started before we
>  	 * trapped to EL2 have completed. This also synchronises the
> -	 * above disabling of BRBE and SPE.
> +	 * above disabling of BRBE.
>  	 *
>  	 * See DDI0487I.a D8.1.5 "Out-of-context translation regimes",
>  	 * rule R_LFHQG and subsequent information statements.
> -- 
> 2.53.0.473.g4a7958ca14-goog
> 


^ permalink raw reply

* Re: [PATCH v10 00/12] barrier: Add smp_cond_load_{relaxed,acquire}_timeout()
From: Catalin Marinas @ 2026-03-25 16:32 UTC (permalink / raw)
  To: David Laight
  Cc: Ankur Arora, Andrew Morton, linux-kernel, linux-arch,
	linux-arm-kernel, linux-pm, bpf, arnd, will, peterz, mark.rutland,
	harisokn, cl, ast, rafael, daniel.lezcano, memxor, zhenglifeng1,
	xueshuai, rdunlap, joao.m.martins, boris.ostrovsky, konrad.wilk
In-Reply-To: <20260325154210.79a621df@pumpkin>

On Wed, Mar 25, 2026 at 03:42:10PM +0000, David Laight wrote:
> On Wed, 25 Mar 2026 13:53:50 +0000
> Catalin Marinas <catalin.marinas@arm.com> wrote:
> 
> > On Tue, Mar 17, 2026 at 09:17:05AM +0000, David Laight wrote:
> > > On Mon, 16 Mar 2026 23:53:22 -0700
> > > Ankur Arora <ankur.a.arora@oracle.com> wrote:  
> > > > David Laight <david.laight.linux@gmail.com> writes:  
> > > > > On arm64 I think you could use explicit sev and wfe - but that will wake all
> > > > > 'sleeping' cpu; and you may not want the 'thundering herd'.    
> > > > 
> > > > Wouldn't we still have the same narrow window where the CPU disregards the IPI?  
> > > 
> > > You need a 'sevl' in the interrupt exit path.  
> > 
> > No need to, see the rule below in
> > https://developer.arm.com/documentation/ddi0487/maa/2983-beijhbbd:
> > 
> > R_XRZRK
> >   The Event Register for a PE is set by any of the following:
> >   [...]
> >   - An exception return.
> > 
> 
> It is a shame the pages for the SEV and WFE instructions don't mention that.
> And the copy I found doesn't have working hyperlinks to any other sections.
> (Not even references to related instructions...)

The latest architecture spec (M.a.a) has working hyperlinks.

> You do need to at least comment that the "msr s0_3_c1_c0_0, %[ecycles]" is
> actually WFET.
> Is that using an absolute cycle count?

Yes, compared to CNTVCT.

> If so does it work if the time has already passed?

Yes, it exits immediately. These counters are not going to wrap in our
(or device's) lifetime.

> If it is absolute do you need to recalculate it every time around the loop?

No but you do need to read CNTVCT, that's what __delay_cycles() does (it
does not wait).

> __delay_cycles() contains guard(preempt_notrace()). I haven't looked what
> that does but is it needed here since preemption is disabled?

The guard was added recently by commit e5cb94ba5f96 ("arm64: Fix
sampling the "stable" virtual counter in preemptible section"). It's
needed for the udelay() case but probably not for Ankur's series. Maybe
we can move the guard in the caller?

> Looking at the code I think the "sevl; wfe" pair should be higher up.

Yes, I replied to your other message. We could move it higher indeed,
before the condition check, but I can't get my head around the ordering.
Can need_resched() check be speculated before the WFE? I need to think
some more.

> I also wonder how long it takes the cpu to leave any low power state.
> We definitely found that was an issue on some x86 cpu and had to both
> disable the lowest low power state and completely rework some wakeup
> code that really wanted a 'thundering herd' rather than the very gentle
> 'bring each cpu out of low power one at a time' that cv_broadcast()
> gave it.

WFE is a very shallow power state where all hardware state is retained.
We have an even stream broadcast to all CPUs regularly already (10KHz)
and I haven't heard people complaining about power degradation. If a CPU
is a WFI state or even deeper into firmware (following a PSCI call), an
exclusive monitor event won't wake it up. It's only for those cores
waiting in WFE.

-- 
Catalin


^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox