On Mon, Aug 17, 2026 at 10:23:33AM +0800, KobaK wrote: > From: Koba Ko <[email protected]> > > Performance characterization on arm64 systems sometimes needs a way to > inspect and bracket selected implementation-defined prefetch and cache > controls without exposing raw register contents. Add an RFC-only arm64 > cpumod interface that presents a small set of named, range-checked > per-CPU sysfs attributes under each CPU device. > > Establish the Kconfig and Makefile plumbing, CPU profile detection for > Grace and Vera from the target CPU's MIDR, register-field descriptors, > per-CPU kobject and attribute helpers, locking, and target-CPU read/write > callbacks. Common attributes are exposed for all supported profiles, > while Grace- and Vera-specific fields are exposed only for the matching > profile. Place the option at the end of the top-level Kernel Features > menu because these implementation controls are not tied to an Arm > architecture revision. > > Per-CPU cpumod sysfs state follows the CPU lifecycle. Module > initialization populates subtrees for every online CPU while holding > cpus_read_lock(), so initial enumeration and CPU hotplug state > registration are serialized against concurrent topology changes. Offline > CPUs are intentionally skipped during initial setup because target-CPU > MIDR detection requires an IPI-capable online CPU; a later online callback > creates their subtree. > > Profile detection reads MIDR through a synchronous callback on the CPU > owning the sysfs subtree and returns nonzero only when that dispatch > fails, so no IPI error can be hidden. After a successful read, retain > CPUMOD_PROFILE_UNKNOWN as the unsupported-profile sentinel. Subtree > creation skips that profile during both initial online enumeration and > later CPUHP online callbacks without blocking module load or CPU hotplug. > Object and sysfs setup failures remain fatal and are propagated. > > Keep the dynamically allocated kobject state in a private per-CPU pointer > instead of the CPU device's generic driver-data slot. The online callback > is idempotent when that pointer already records a subtree. The offline > callback clears the private pointer before dropping the kobject reference, > allowing the release callback to retain ownership of the final free. > > Register the dynamic CPUHP state with > cpuhp_setup_state_nocalls_cpuslocked(). The nocalls form avoids replaying > startup callbacks for CPUs already initialized by the explicit online > enumeration. On init failure, release the CPU read lock, destroy all > subtrees created so far, and return the error. Module exit removes the > CPUHP state with the matching nocalls helper and tears down all remaining > per-CPU state across possible CPUs. > > Reviewed-by: Fenghua Yu <[email protected]> > Reviewed-by: Tushar Dave <[email protected]> > Reviewed-by: Kai-Heng Feng <[email protected]> > Signed-off-by: Koba Ko <[email protected]>
Tested-by: Breno Leitao <[email protected]> > +static struct cpumod_attr _name##_attr = { \ > + .kattr = __ATTR(_name, 0644, cpumod_attr_show, cpumod_attr_store), \ > + .value_offset = offsetof(struct cpumod_subsys, _field), \ > + .reg = _reg, \ > + .shift = _shift, \ > + .field_mask = _field_mask, \ > + .max_value = _max_value, \ > + .debug_name = _debug_name, \ > + .visible_profiles = _visible_profiles, \ > +} 0644 makes every one of these world-readable, and cpumod_attr_show() is not a cheap read: it takes subsys->lock and then does a synchronous smp_call_function_single() to the target CPU, whose callback executes an implementation-defined mrs. So any unprivileged user can pick a CPU and hold it under a steady stream of IPIs just by reading the file in a loop. On a Grace box running this series: # su -s /bin/sh nobody -c 'cat /sys/devices/system/cpu/cpu0/cpumod/pf_dis' 0

