Skip to content

Commit 332d6a9

Browse files
committed
Merge tag 'cpufreq-arm-fixes-6.16-rc' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm
Merge CPUFreq fixes for 6.16-rc from Viresh Kumar: "- Implement CpuId rust abstraction and use it to fix doctest failure (Viresh Kumar). - Minor cleanups in the `# Safety` sections for cpufreq abstractions (Viresh Kumar)." * tag 'cpufreq-arm-fixes-6.16-rc' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm: rust: cpu: Add CpuId::current() to retrieve current CPU ID rust: Use CpuId in place of raw CPU numbers rust: cpu: Introduce CpuId abstraction cpufreq: Convert `/// SAFETY` lines to `# Safety` sections
2 parents 19272b3 + c7f005f commit 332d6a9

File tree

7 files changed

+299
-64
lines changed

7 files changed

+299
-64
lines changed

MAINTAINERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6254,6 +6254,7 @@ F: include/linux/cpuhotplug.h
62546254
F: include/linux/smpboot.h
62556255
F: kernel/cpu.c
62566256
F: kernel/smpboot.*
6257+
F: rust/helper/cpu.c
62576258
F: rust/kernel/cpu.rs
62586259

62596260
CPU IDLE TIME MANAGEMENT FRAMEWORK

drivers/cpufreq/rcpufreq_dt.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ fn find_supply_name_exact(dev: &Device, name: &str) -> Option<CString> {
2626
}
2727

2828
/// Finds supply name for the CPU from DT.
29-
fn find_supply_names(dev: &Device, cpu: u32) -> Option<KVec<CString>> {
29+
fn find_supply_names(dev: &Device, cpu: cpu::CpuId) -> Option<KVec<CString>> {
3030
// Try "cpu0" for older DTs, fallback to "cpu".
31-
let name = (cpu == 0)
31+
let name = (cpu.as_u32() == 0)
3232
.then(|| find_supply_name_exact(dev, "cpu0"))
3333
.flatten()
3434
.or_else(|| find_supply_name_exact(dev, "cpu"))?;

rust/helpers/cpu.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#include <linux/smp.h>
4+
5+
unsigned int rust_helper_raw_smp_processor_id(void)
6+
{
7+
return raw_smp_processor_id();
8+
}

rust/helpers/helpers.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "build_assert.c"
1414
#include "build_bug.c"
1515
#include "clk.c"
16+
#include "cpu.c"
1617
#include "cpufreq.c"
1718
#include "cpumask.c"
1819
#include "cred.c"

rust/kernel/cpu.rs

Lines changed: 123 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,127 @@
66
77
use crate::{bindings, device::Device, error::Result, prelude::ENODEV};
88

9+
/// Returns the maximum number of possible CPUs in the current system configuration.
10+
#[inline]
11+
pub fn nr_cpu_ids() -> u32 {
12+
#[cfg(any(NR_CPUS_1, CONFIG_FORCE_NR_CPUS))]
13+
{
14+
bindings::NR_CPUS
15+
}
16+
17+
#[cfg(not(any(NR_CPUS_1, CONFIG_FORCE_NR_CPUS)))]
18+
// SAFETY: `nr_cpu_ids` is a valid global provided by the kernel.
19+
unsafe {
20+
bindings::nr_cpu_ids
21+
}
22+
}
23+
24+
/// The CPU ID.
25+
///
26+
/// Represents a CPU identifier as a wrapper around an [`u32`].
27+
///
28+
/// # Invariants
29+
///
30+
/// The CPU ID lies within the range `[0, nr_cpu_ids())`.
31+
///
32+
/// # Examples
33+
///
34+
/// ```
35+
/// use kernel::cpu::CpuId;
36+
///
37+
/// let cpu = 0;
38+
///
39+
/// // SAFETY: 0 is always a valid CPU number.
40+
/// let id = unsafe { CpuId::from_u32_unchecked(cpu) };
41+
///
42+
/// assert_eq!(id.as_u32(), cpu);
43+
/// assert!(CpuId::from_i32(0).is_some());
44+
/// assert!(CpuId::from_i32(-1).is_none());
45+
/// ```
46+
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
47+
pub struct CpuId(u32);
48+
49+
impl CpuId {
50+
/// Creates a new [`CpuId`] from the given `id` without checking bounds.
51+
///
52+
/// # Safety
53+
///
54+
/// The caller must ensure that `id` is a valid CPU ID (i.e., `0 <= id < nr_cpu_ids()`).
55+
#[inline]
56+
pub unsafe fn from_i32_unchecked(id: i32) -> Self {
57+
debug_assert!(id >= 0);
58+
debug_assert!((id as u32) < nr_cpu_ids());
59+
60+
// INVARIANT: The function safety guarantees `id` is a valid CPU id.
61+
Self(id as u32)
62+
}
63+
64+
/// Creates a new [`CpuId`] from the given `id`, checking that it is valid.
65+
pub fn from_i32(id: i32) -> Option<Self> {
66+
if id < 0 || id as u32 >= nr_cpu_ids() {
67+
None
68+
} else {
69+
// INVARIANT: `id` has just been checked as a valid CPU ID.
70+
Some(Self(id as u32))
71+
}
72+
}
73+
74+
/// Creates a new [`CpuId`] from the given `id` without checking bounds.
75+
///
76+
/// # Safety
77+
///
78+
/// The caller must ensure that `id` is a valid CPU ID (i.e., `0 <= id < nr_cpu_ids()`).
79+
#[inline]
80+
pub unsafe fn from_u32_unchecked(id: u32) -> Self {
81+
debug_assert!(id < nr_cpu_ids());
82+
83+
// Ensure the `id` fits in an [`i32`] as it's also representable that way.
84+
debug_assert!(id <= i32::MAX as u32);
85+
86+
// INVARIANT: The function safety guarantees `id` is a valid CPU id.
87+
Self(id)
88+
}
89+
90+
/// Creates a new [`CpuId`] from the given `id`, checking that it is valid.
91+
pub fn from_u32(id: u32) -> Option<Self> {
92+
if id >= nr_cpu_ids() {
93+
None
94+
} else {
95+
// INVARIANT: `id` has just been checked as a valid CPU ID.
96+
Some(Self(id))
97+
}
98+
}
99+
100+
/// Returns CPU number.
101+
#[inline]
102+
pub fn as_u32(&self) -> u32 {
103+
self.0
104+
}
105+
106+
/// Returns the ID of the CPU the code is currently running on.
107+
///
108+
/// The returned value is considered unstable because it may change
109+
/// unexpectedly due to preemption or CPU migration. It should only be
110+
/// used when the context ensures that the task remains on the same CPU
111+
/// or the users could use a stale (yet valid) CPU ID.
112+
pub fn current() -> Self {
113+
// SAFETY: raw_smp_processor_id() always returns a valid CPU ID.
114+
unsafe { Self::from_u32_unchecked(bindings::raw_smp_processor_id()) }
115+
}
116+
}
117+
118+
impl From<CpuId> for u32 {
119+
fn from(id: CpuId) -> Self {
120+
id.as_u32()
121+
}
122+
}
123+
124+
impl From<CpuId> for i32 {
125+
fn from(id: CpuId) -> Self {
126+
id.as_u32() as i32
127+
}
128+
}
129+
9130
/// Creates a new instance of CPU's device.
10131
///
11132
/// # Safety
@@ -17,9 +138,9 @@ use crate::{bindings, device::Device, error::Result, prelude::ENODEV};
17138
/// Callers must ensure that the CPU device is not used after it has been unregistered.
18139
/// This can be achieved, for example, by registering a CPU hotplug notifier and removing
19140
/// any references to the CPU device within the notifier's callback.
20-
pub unsafe fn from_cpu(cpu: u32) -> Result<&'static Device> {
141+
pub unsafe fn from_cpu(cpu: CpuId) -> Result<&'static Device> {
21142
// SAFETY: It is safe to call `get_cpu_device()` for any CPU.
22-
let ptr = unsafe { bindings::get_cpu_device(cpu) };
143+
let ptr = unsafe { bindings::get_cpu_device(u32::from(cpu)) };
23144
if ptr.is_null() {
24145
return Err(ENODEV);
25146
}

0 commit comments

Comments
 (0)