From nobody Sat Oct 11 12:05:11 2025 Received: from mail-pl1-f179.google.com (mail-pl1-f179.google.com [209.85.214.179]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D995823ABA1 for ; Tue, 10 Jun 2025 13:22:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.179 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749561730; cv=none; b=UFsXKTLVTf2AP5n2KLhoNA4OpUuGvFfeOvEsH1Xf5HSb8PdnbjR+HOpQnp4DhqK7YEMeOPaEHAgrGo7qzdUCszq4UHgSb/KNTQz7WHsARPrjXzxAtSqoYpVkBDMLfeXl6lFoLzXJTqukc+g2g9/V3q1BxEpBpG0GE+644jdv7uQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749561730; c=relaxed/simple; bh=R2pZaS4Inj+1kow0TGmJZeY+hDxhkzLhakpOlf2UzU4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=d+YVE46IH+gnu7jb3yEkxOvoAhLcfKFFT2mdICtoGJNVY6NqWWJdtnGJN9GMcnsKmCDzmAcxLzeC8YvhcadOfHm3c1rji7pWm+41owtIckQhi9Rn8Zt+sRRojU1gUO4wmNI3KrOOywQcBRNJ4/K8xDii2O+NYPMjcAX3sLCbE0c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=Cq2BxIWT; arc=none smtp.client-ip=209.85.214.179 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="Cq2BxIWT" Received: by mail-pl1-f179.google.com with SMTP id d9443c01a7336-234d366e5f2so61536945ad.1 for ; Tue, 10 Jun 2025 06:22:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1749561728; x=1750166528; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=YVEmdQ83ragxEJ1AiZ1OnaThOc00e/tBKCQz7GkXCKw=; b=Cq2BxIWTwjISN9qrtEcs1Br3mK3OqE/I/zur9TMATUuEhDWhpbDZslVRezBJV9EAer Q/4xM4NXsJxqpIqCsFHz/tLozlhgf26paFnz+rXUXblt6qQG9TjWaXm39j6y6vSgyGH0 gm2ZQY6wRXOvAOI27WGYhNWPvKLau0/jm27RHDGvaJniUo20PvkQEjlGRnP0oQ46Y1Vj K3lFxvGC+hxTUIquwigtFhKkHQyJSDePbJ/gn8ckW/nNWzD9SLrGnjHD7qqK0zOsifUa e+lD4ARw2bafxyvmMd0eAqaxyv/m58n+FlV4d6OiTzNpLRW7MeXNsNsGwtKa/ya5xj88 W5Kg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749561728; x=1750166528; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=YVEmdQ83ragxEJ1AiZ1OnaThOc00e/tBKCQz7GkXCKw=; b=VpsJlajDWS39ShMmpM6PGRA/ImtPoXpvmLw4K0tgLvsrUhgUd7CrsSIRyZrbG4zSCu 9FxOlTlhL/S/vUdIO1cqH+eTNMqU2Qvx7rH7FktcY4GZknnRpqq/oK7zhjIXzHkJCQIX IpmBmsPIn2VWH7VunQ84qjkU9etTArEDVsgtjtM09rbUSlyLZ8rQqyusRkhu3g27zqnb 2ncMWlFw1fGz4acYdCVr1U8cz3DamJfD94sLPeSuWluda3bhgqADu86d7ELKWNe5lhYt wRCSCDLuQyTM58trfOzMqZBSMDgGMnbfIYC5GNA3YrDPKJoE3mAHZFep0YViYh//Kdnp dwGQ== X-Forwarded-Encrypted: i=1; AJvYcCXK7DQMwSfq9DhW3Fvxe49O6MUQ6/srwvEq9oVLkLQvtUlmWqMggf7if5Pd2Y/dNS3QBGc7KML3PUZAH8g=@vger.kernel.org X-Gm-Message-State: AOJu0Yzf/62a0nSGWKqJ3t5fhOnkuliBvPaVbYLJPGFNLFxw92Efjy5t k2lS6fPr9zNYPRzck7oVQM+qxANeW9mNmd17wmYvbVFcULnULlmDPdSY2tWv8E/mdGs= X-Gm-Gg: ASbGncu7KKCc2O4rbA2gXRdNfqruZgE7WJSZpCeyoawEOnuRrVPRCwOCVNAjBx18Qgu MMSw63wu+s1J6Oy5PMstRAosmd7jHMboZWQwDHZLLDyM+uNmFK5h33FfmKaSyyokiLQ83c3pJFN +WLQXaHW0pkOudns/8TRVS9E4T2WPTAlcKX9aVgitYxfJ9K5Y9f+bdzTjYFgMfJTPV5fRfZ9Nl9 3Yo0BulRuCijZ9tr+wPKr5+/2XqJmojvLdp6kl413vhOh4vYIsecdf3VJ/XD9klWr3BWLHtuWcD M3TOVZklhg4+MUTfTRrcPNhpUeL61c4HAh5+VKVPcLuE2au4SVKUvxsKwxeT3jQ= X-Google-Smtp-Source: AGHT+IGx5k83MsrhLinmP85CumO7M2Xp1AotBfN/2FVNNvRad0ckpgu3dDBIvaj43xzWCic7a/kotA== X-Received: by 2002:a17:902:e741:b0:235:668:fb00 with SMTP id d9443c01a7336-23601de827dmr248498635ad.46.1749561728237; Tue, 10 Jun 2025 06:22:08 -0700 (PDT) Received: from localhost ([122.172.81.72]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-236034059b3sm70224065ad.175.2025.06.10.06.22.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 10 Jun 2025 06:22:07 -0700 (PDT) From: Viresh Kumar To: Boqun Feng , "Rafael J. Wysocki" , Thomas Gleixner , Peter Zijlstra , Miguel Ojeda , Alex Gaynor , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich Cc: Viresh Kumar , Vincent Guittot , Yury Norov , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH V3 1/3] rust: cpu: Introduce CpuId abstraction Date: Tue, 10 Jun 2025 18:51:56 +0530 Message-Id: X-Mailer: git-send-email 2.31.1.272.g89b43f80a514 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This adds abstraction for representing a CPU identifier. Suggested-by: Boqun Feng Signed-off-by: Viresh Kumar Reviewed-by: Boqun Feng --- rust/kernel/cpu.rs | 110 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/rust/kernel/cpu.rs b/rust/kernel/cpu.rs index 10c5c3b25873..6a3aecb12468 100644 --- a/rust/kernel/cpu.rs +++ b/rust/kernel/cpu.rs @@ -6,6 +6,116 @@ =20 use crate::{bindings, device::Device, error::Result, prelude::ENODEV}; =20 +/// Returns the maximum number of possible CPUs in the current system conf= iguration. +#[inline] +pub fn nr_cpu_ids() -> u32 { + #[cfg(any(NR_CPUS_1, CONFIG_FORCE_NR_CPUS))] + { + bindings::NR_CPUS + } + + #[cfg(not(any(NR_CPUS_1, CONFIG_FORCE_NR_CPUS)))] + // SAFETY: `nr_cpu_ids` is a valid global provided by the kernel. + unsafe { + bindings::nr_cpu_ids + } +} + +/// The CPU ID. +/// +/// Represents a CPU identifier as a wrapper around an [`u32`]. +/// +/// # Invariants +/// +/// The CPU ID lies within the range `[0, nr_cpu_ids())`. +/// +/// # Examples +/// +/// ``` +/// use kernel::cpu::CpuId; +/// +/// let cpu =3D 0; +/// +/// // SAFETY: 0 is always a valid CPU number. +/// let id =3D unsafe { CpuId::from_u32_unchecked(cpu) }; +/// +/// assert_eq!(id.as_u32(), cpu); +/// assert!(CpuId::from_i32(0).is_some()); +/// assert!(CpuId::from_i32(-1).is_none()); +/// ``` +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub struct CpuId(u32); + +impl CpuId { + /// Creates a new [`CpuId`] from the given `id` without checking bound= s. + /// + /// # Safety + /// + /// The caller must ensure that `id` is a valid CPU ID (i.e., `0 <=3D = id < nr_cpu_ids()`). + #[inline] + pub unsafe fn from_i32_unchecked(id: i32) -> Self { + debug_assert!(id >=3D 0); + debug_assert!((id as u32) < nr_cpu_ids()); + + // INVARIANT: The function safety guarantees `id` is a valid CPU i= d. + Self(id as u32) + } + + /// Creates a new [`CpuId`] from the given `id`, checking that it is v= alid. + pub fn from_i32(id: i32) -> Option { + if id < 0 || id as u32 >=3D nr_cpu_ids() { + None + } else { + // INVARIANT: `id` has just been checked as a valid CPU ID. + Some(Self(id as u32)) + } + } + + /// Creates a new [`CpuId`] from the given `id` without checking bound= s. + /// + /// # Safety + /// + /// The caller must ensure that `id` is a valid CPU ID (i.e., `0 <=3D = id < nr_cpu_ids()`). + #[inline] + pub unsafe fn from_u32_unchecked(id: u32) -> Self { + debug_assert!(id < nr_cpu_ids()); + + // Ensure the `id` fits in an [`i32`] as it's also representable t= hat way. + debug_assert!(id <=3D i32::MAX as u32); + + // INVARIANT: The function safety guarantees `id` is a valid CPU i= d. + Self(id) + } + + /// Creates a new [`CpuId`] from the given `id`, checking that it is v= alid. + pub fn from_u32(id: u32) -> Option { + if id >=3D nr_cpu_ids() { + None + } else { + // INVARIANT: `id` has just been checked as a valid CPU ID. + Some(Self(id)) + } + } + + /// Returns CPU number. + #[inline] + pub fn as_u32(&self) -> u32 { + self.0 + } +} + +impl From for u32 { + fn from(id: CpuId) -> Self { + id.as_u32() + } +} + +impl From for i32 { + fn from(id: CpuId) -> Self { + id.as_u32() as i32 + } +} + /// Creates a new instance of CPU's device. /// /// # Safety --=20 2.31.1.272.g89b43f80a514 From nobody Sat Oct 11 12:05:11 2025 Received: from mail-pg1-f176.google.com (mail-pg1-f176.google.com [209.85.215.176]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8ABDE295DB8 for ; Tue, 10 Jun 2025 13:22:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.176 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749561735; cv=none; b=l8yyNexALb0Nd/1ZP/5z5CvjQlwCZKONoxL9j8mgLcaA6S0By1wBnxE0x8Hod4Ek4pj7l75kJWaReMjAyIUKMgW52X+B+KbCLpQ2p8ipAD1b0nfISH9XcSVzahZ4RZZZnsRkngJhWq1wyn9qH6NfIoprTApMRWtIRn6zMi/NaW8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749561735; c=relaxed/simple; bh=pg9//lGKC5q7jStTMIlzjM/+UsizaQyTQXjdeOlLvIo=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=AtqfsMgR5Y+WjyhFboMkDLCBYxLYQCkNxFq2UrNZobKPH2ywQ8V0DTYy3iSOVQOz8hncvPfPLsM4BhFOVUK6oqR+TYPYX8Z84qa5l6p2wDCflKA83K3Es5ynUlhylaDh1tiO2sCAXTSjehKSYSsWNFCBSb5Ynnj8gbgjnUJ/Mxk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=cvzgMufQ; arc=none smtp.client-ip=209.85.215.176 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="cvzgMufQ" Received: by mail-pg1-f176.google.com with SMTP id 41be03b00d2f7-b2f11866376so3571301a12.3 for ; Tue, 10 Jun 2025 06:22:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1749561733; x=1750166533; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=3vGS9bFhaItWzg1MY3+mfwEAkDgZMtZN5zzSGR+CYpA=; b=cvzgMufQmsGsaLmBr7x6nJEu5g+XCA90uGxEfxhM06qRXNrQkCVqeIamRBSaYo45Hw 94EvpwYaNhK0GcZDAxfs/pOeKGJ48OivnnerijdeHnpaArlOcsPA4OSySmMMEG95c85R DaKrcU7l1Kb0O9tIrsIfdEYqMoJzLkS5YOA/FtumabACqwnILOrrm5ecYblJfqUwkT8K 1mFnMdp1WPO0fBWOXVzWuX8d7yp+JsQc+9vvKbIzQ+4hMSvbz16kkQboOi6b6h+CBdZP FF4MXteeboANe4/Sp3h3XF4O+il/CaNsICayDKC1nsRvyMIEdta5Jg3cudMd1uFXQBSK xfIw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749561733; x=1750166533; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=3vGS9bFhaItWzg1MY3+mfwEAkDgZMtZN5zzSGR+CYpA=; b=cr8wnXrGcj19oPDllQtQ2vzCXLBJrrO5ZTN3WtHu/rYImoLgiWZAXG+JHimd+WwD/N +NeayvOpdyXyHw4d0cQXftCEiqPX4l6UIEq+yvNJFQ19XPPTKa/FE7LEGDQSsFKF9hT5 OtGJQJHPhvFC5fC3eoL2/H2JrWHna5Rt18NiWRaRi4d9Xtc64r8E8P6rsZ0SUn+mjez5 V188UX1hK4ooANl/y3trZzuIcCw2Unlpi9mAKZ0ifaiC6GEfQgWGrgPWRj9ie44vqKz+ sJfJ4avbUZxqoZmRLi22Im4/ygRyeNdLeSrzgXioIYqXqJ2Ai7MvPDBkXr7sSrekXolx V1/w== X-Forwarded-Encrypted: i=1; AJvYcCVW2WDT+9Jxia1/F/WyHDCI1nVRCx+s78tf1n+f9a0T6bcUwhbUUh9ev8U47eulqTS/ipxLMZFnvopDdbc=@vger.kernel.org X-Gm-Message-State: AOJu0Yz3WZdtidHzV+q0b7xw6hNLZftjKt5S31oJWZxwO0edtWfCWJLb ppDBZsmpVgl7Gy3+ouf6Fa7m72KUqqJKY2iTLuq7VDa/0V9A/CIIUfVTxAOc+OFKxxw= X-Gm-Gg: ASbGncuMewmxBadmKw08wr4uW6anXwlCf2Z+WiaeJOLZqzJX8NQ4uGGEuiVsgcqnwUc KMJxFnlEEcO9+ScZFs8IvWFIG6I2LEqSW+B1l3WQWdrvMH42K9exBQskjXmWmP3LyuEdM7v2QY6 /L+oeN3J0eMxkbObxDxPdLPzPGI5tIusqoQidfkvqv7NhZo8zgbDVniyADvlaY0UyAlHISbHNyZ Exoy5+om6XjWWkFtyj8/AJu/6UHYPlSJiU0iFilQwpG0fv98A0vGmbBAM2i4FYmfM56E748ZeJG jSg6CQ/NjZcR9CP7CfreFiAimiu+NUxc+NAFnCgSToNyieJOYUbvjhkIMoGUMT0= X-Google-Smtp-Source: AGHT+IGjFiliPKrObq5ltswR8UB2srN9m8x8jJE9BnDPvMHBx3FP7jXqQwepXBVXuRD19df18OKJqw== X-Received: by 2002:a17:90b:5107:b0:313:5d2f:54f8 with SMTP id 98e67ed59e1d1-3135d2f5588mr22158152a91.33.1749561732026; Tue, 10 Jun 2025 06:22:12 -0700 (PDT) Received: from localhost ([122.172.81.72]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-3134b180dbesm7947163a91.48.2025.06.10.06.22.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 10 Jun 2025 06:22:11 -0700 (PDT) From: Viresh Kumar To: Boqun Feng , "Rafael J. Wysocki" , Viresh Kumar , Thomas Gleixner , Peter Zijlstra , Miguel Ojeda , Alex Gaynor , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Yury Norov Cc: Vincent Guittot , rust-for-linux@vger.kernel.org, linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH V3 2/3] rust: Use CpuId in place of raw CPU numbers Date: Tue, 10 Jun 2025 18:51:57 +0530 Message-Id: X-Mailer: git-send-email 2.31.1.272.g89b43f80a514 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Use the newly defined `CpuId` abstraction instead of raw CPU numbers. This also fixes a doctest failure for configurations where `nr_cpu_ids < 4`. The C `cpumask_{set|clear}_cpu()` APIs emit a warning when given an invalid CPU number =E2=80=94 but only if `CONFIG_DEBUG_PER_CPU_MAPS=3Dy` is= set. Meanwhile, `cpumask_weight()` only considers CPUs up to `nr_cpu_ids`, which can cause inconsistencies: a CPU number greater than `nr_cpu_ids` may be set in the mask, yet the weight calculation won't reflect it. This leads to doctest failures when `nr_cpu_ids < 4`, as the test tries to set CPUs 2 and 3: rust_doctest_kernel_cpumask_rs_0.location: rust/kernel/cpumask.rs:180 rust_doctest_kernel_cpumask_rs_0: ASSERTION FAILED at rust/kernel/cpumask= .rs:190 Fixes: 8961b8cb3099 ("rust: cpumask: Add initial abstractions") Reported-by: Miguel Ojeda Closes: https://lore.kernel.org/rust-for-linux/CANiq72k3ozKkLMinTLQwvkyg9K= =3DBeRxs1oYZSKhJHY-veEyZdg@mail.gmail.com/ Reported-by: Andreas Hindborg Closes: https://lore.kernel.org/all/87qzzy3ric.fsf@kernel.org/ Suggested-by: Boqun Feng Signed-off-by: Viresh Kumar Reviewed-by: Boqun Feng --- drivers/cpufreq/rcpufreq_dt.rs | 4 +-- rust/kernel/cpu.rs | 4 +-- rust/kernel/cpufreq.rs | 27 ++++++++++++------ rust/kernel/cpumask.rs | 51 ++++++++++++++++++++++++---------- 4 files changed, 59 insertions(+), 27 deletions(-) diff --git a/drivers/cpufreq/rcpufreq_dt.rs b/drivers/cpufreq/rcpufreq_dt.rs index 94ed81644fe1..43c87d0259b6 100644 --- a/drivers/cpufreq/rcpufreq_dt.rs +++ b/drivers/cpufreq/rcpufreq_dt.rs @@ -26,9 +26,9 @@ fn find_supply_name_exact(dev: &Device, name: &str) -> Op= tion { } =20 /// Finds supply name for the CPU from DT. -fn find_supply_names(dev: &Device, cpu: u32) -> Option> { +fn find_supply_names(dev: &Device, cpu: cpu::CpuId) -> Option> { // Try "cpu0" for older DTs, fallback to "cpu". - let name =3D (cpu =3D=3D 0) + let name =3D (cpu.as_u32() =3D=3D 0) .then(|| find_supply_name_exact(dev, "cpu0")) .flatten() .or_else(|| find_supply_name_exact(dev, "cpu"))?; diff --git a/rust/kernel/cpu.rs b/rust/kernel/cpu.rs index 6a3aecb12468..7549594fad7f 100644 --- a/rust/kernel/cpu.rs +++ b/rust/kernel/cpu.rs @@ -127,9 +127,9 @@ fn from(id: CpuId) -> Self { /// Callers must ensure that the CPU device is not used after it has been = unregistered. /// This can be achieved, for example, by registering a CPU hotplug notifi= er and removing /// any references to the CPU device within the notifier's callback. -pub unsafe fn from_cpu(cpu: u32) -> Result<&'static Device> { +pub unsafe fn from_cpu(cpu: CpuId) -> Result<&'static Device> { // SAFETY: It is safe to call `get_cpu_device()` for any CPU. - let ptr =3D unsafe { bindings::get_cpu_device(cpu) }; + let ptr =3D unsafe { bindings::get_cpu_device(cpu.into()) }; if ptr.is_null() { return Err(ENODEV); } diff --git a/rust/kernel/cpufreq.rs b/rust/kernel/cpufreq.rs index 9b995f18aac6..ea6106db5c29 100644 --- a/rust/kernel/cpufreq.rs +++ b/rust/kernel/cpufreq.rs @@ -10,6 +10,7 @@ =20 use crate::{ clk::Hertz, + cpu::CpuId, cpumask, device::{Bound, Device}, devres::Devres, @@ -465,8 +466,9 @@ fn as_mut_ref(&mut self) -> &mut bindings::cpufreq_poli= cy { =20 /// Returns the primary CPU for the [`Policy`]. #[inline] - pub fn cpu(&self) -> u32 { - self.as_ref().cpu + pub fn cpu(&self) -> CpuId { + // SAFETY: The C API guarantees that `cpu` refers to a valid CPU n= umber. + unsafe { CpuId::from_u32_unchecked(self.as_ref().cpu) } } =20 /// Returns the minimum frequency for the [`Policy`]. @@ -525,7 +527,7 @@ pub fn generic_suspend(&mut self) -> Result { #[inline] pub fn generic_get(&self) -> Result { // SAFETY: By the type invariant, the pointer stored in `self` is = valid. - Ok(unsafe { bindings::cpufreq_generic_get(self.cpu()) }) + Ok(unsafe { bindings::cpufreq_generic_get(self.cpu().into()) }) } =20 /// Provides a wrapper to the register with energy model using the OPP= core. @@ -678,9 +680,9 @@ fn clear_data(&mut self) -> Option { struct PolicyCpu<'a>(&'a mut Policy); =20 impl<'a> PolicyCpu<'a> { - fn from_cpu(cpu: u32) -> Result { + fn from_cpu(cpu: CpuId) -> Result { // SAFETY: It is safe to call `cpufreq_cpu_get` for any valid CPU. - let ptr =3D from_err_ptr(unsafe { bindings::cpufreq_cpu_get(cpu) }= )?; + let ptr =3D from_err_ptr(unsafe { bindings::cpufreq_cpu_get(cpu.in= to()) })?; =20 Ok(Self( // SAFETY: The `ptr` is guaranteed to be valid and remains val= id for the lifetime of @@ -1266,7 +1268,10 @@ impl Registration { target_perf: usize, capacity: usize, ) { - if let Ok(mut policy) =3D PolicyCpu::from_cpu(cpu) { + // SAFETY: The C API guarantees that `cpu` refers to a valid CPU n= umber. + let cpu_id =3D unsafe { CpuId::from_u32_unchecked(cpu) }; + + if let Ok(mut policy) =3D PolicyCpu::from_cpu(cpu_id) { T::adjust_perf(&mut policy, min_perf, target_perf, capacity); } } @@ -1321,7 +1326,10 @@ impl Registration { /// /// - This function may only be called from the cpufreq C infrastructu= re. unsafe extern "C" fn get_callback(cpu: u32) -> kernel::ffi::c_uint { - PolicyCpu::from_cpu(cpu).map_or(0, |mut policy| T::get(&mut policy= ).map_or(0, |f| f)) + // SAFETY: The C API guarantees that `cpu` refers to a valid CPU n= umber. + let cpu_id =3D unsafe { CpuId::from_u32_unchecked(cpu) }; + + PolicyCpu::from_cpu(cpu_id).map_or(0, |mut policy| T::get(&mut pol= icy).map_or(0, |f| f)) } =20 /// Driver's `update_limit` callback. @@ -1344,8 +1352,11 @@ impl Registration { /// - This function may only be called from the cpufreq C infrastructu= re. /// - The pointer arguments must be valid pointers. unsafe extern "C" fn bios_limit_callback(cpu: i32, limit: *mut u32) ->= kernel::ffi::c_int { + // SAFETY: The C API guarantees that `cpu` refers to a valid CPU n= umber. + let cpu_id =3D unsafe { CpuId::from_i32_unchecked(cpu) }; + from_result(|| { - let mut policy =3D PolicyCpu::from_cpu(cpu as u32)?; + let mut policy =3D PolicyCpu::from_cpu(cpu_id)?; =20 // SAFETY: `limit` is guaranteed by the C code to be valid. T::bios_limit(&mut policy, &mut (unsafe { *limit })).map(|()| = 0) diff --git a/rust/kernel/cpumask.rs b/rust/kernel/cpumask.rs index c90bfac9346a..11ddd43edcb5 100644 --- a/rust/kernel/cpumask.rs +++ b/rust/kernel/cpumask.rs @@ -6,6 +6,7 @@ =20 use crate::{ alloc::{AllocError, Flags}, + cpu::CpuId, prelude::*, types::Opaque, }; @@ -35,9 +36,10 @@ /// /// ``` /// use kernel::bindings; +/// use kernel::cpu::CpuId; /// use kernel::cpumask::Cpumask; /// -/// fn set_clear_cpu(ptr: *mut bindings::cpumask, set_cpu: u32, clear_cpu:= i32) { +/// fn set_clear_cpu(ptr: *mut bindings::cpumask, set_cpu: CpuId, clear_cp= u: CpuId) { /// // SAFETY: The `ptr` is valid for writing and remains valid for th= e lifetime of the /// // returned reference. /// let mask =3D unsafe { Cpumask::as_mut_ref(ptr) }; @@ -90,9 +92,9 @@ pub fn as_raw(&self) -> *mut bindings::cpumask { /// This mismatches kernel naming convention and corresponds to the C /// function `__cpumask_set_cpu()`. #[inline] - pub fn set(&mut self, cpu: u32) { + pub fn set(&mut self, cpu: CpuId) { // SAFETY: By the type invariant, `self.as_raw` is a valid argumen= t to `__cpumask_set_cpu`. - unsafe { bindings::__cpumask_set_cpu(cpu, self.as_raw()) }; + unsafe { bindings::__cpumask_set_cpu(cpu.into(), self.as_raw()) }; } =20 /// Clear `cpu` in the cpumask. @@ -101,19 +103,19 @@ pub fn set(&mut self, cpu: u32) { /// This mismatches kernel naming convention and corresponds to the C /// function `__cpumask_clear_cpu()`. #[inline] - pub fn clear(&mut self, cpu: i32) { + pub fn clear(&mut self, cpu: CpuId) { // SAFETY: By the type invariant, `self.as_raw` is a valid argumen= t to // `__cpumask_clear_cpu`. - unsafe { bindings::__cpumask_clear_cpu(cpu, self.as_raw()) }; + unsafe { bindings::__cpumask_clear_cpu(cpu.into(), self.as_raw()) = }; } =20 /// Test `cpu` in the cpumask. /// /// Equivalent to the kernel's `cpumask_test_cpu` API. #[inline] - pub fn test(&self, cpu: i32) -> bool { + pub fn test(&self, cpu: CpuId) -> bool { // SAFETY: By the type invariant, `self.as_raw` is a valid argumen= t to `cpumask_test_cpu`. - unsafe { bindings::cpumask_test_cpu(cpu, self.as_raw()) } + unsafe { bindings::cpumask_test_cpu(cpu.into(), self.as_raw()) } } =20 /// Set all CPUs in the cpumask. @@ -178,21 +180,40 @@ pub fn copy(&self, dstp: &mut Self) { /// The following example demonstrates how to create and update a [`Cpumas= kVar`]. /// /// ``` +/// use kernel::cpu::CpuId; /// use kernel::cpumask::CpumaskVar; /// /// let mut mask =3D CpumaskVar::new_zero(GFP_KERNEL).unwrap(); /// /// assert!(mask.empty()); -/// mask.set(2); -/// assert!(mask.test(2)); -/// mask.set(3); -/// assert!(mask.test(3)); -/// assert_eq!(mask.weight(), 2); +/// let mut count =3D 0; +/// +/// let cpu2 =3D CpuId::from_u32(2); +/// if let Some(cpu) =3D cpu2 { +/// mask.set(cpu); +/// assert!(mask.test(cpu)); +/// count +=3D 1; +/// } +/// +/// let cpu3 =3D CpuId::from_u32(3); +/// if let Some(cpu) =3D cpu3 { +/// mask.set(cpu); +/// assert!(mask.test(cpu)); +/// count +=3D 1; +/// } +/// +/// assert_eq!(mask.weight(), count); /// /// let mask2 =3D CpumaskVar::try_clone(&mask).unwrap(); -/// assert!(mask2.test(2)); -/// assert!(mask2.test(3)); -/// assert_eq!(mask2.weight(), 2); +/// +/// if let Some(cpu) =3D cpu2 { +/// assert!(mask2.test(cpu)); +/// } +/// +/// if let Some(cpu) =3D cpu3 { +/// assert!(mask2.test(cpu)); +/// } +/// assert_eq!(mask2.weight(), count); /// ``` pub struct CpumaskVar { #[cfg(CONFIG_CPUMASK_OFFSTACK)] --=20 2.31.1.272.g89b43f80a514 From nobody Sat Oct 11 12:05:11 2025 Received: from mail-pl1-f180.google.com (mail-pl1-f180.google.com [209.85.214.180]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8C7F2298CDC for ; Tue, 10 Jun 2025 13:22:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.180 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749561738; cv=none; b=eZr84ghEopJ5PQ5N/RVban+NOF4DSWK+Z4Ljhn23kjYnXQcp6oI46ykgAVTncaIzhgsIJjEGnYKdEa77JXv+pmKWY8Kdnxm5KxykfJhpPOFAz2FPvwRUR55PPqkyAR4NXhnS0yVKa/eQP8qlCVDGJin9H0yy//dQF87vdPUyJz8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749561738; c=relaxed/simple; bh=1trWxBrPAl76fxmsb+oeXOY/Ya77z6kO/+mfRMr7pEk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=j4ziJOJSOfbfg6mqRpXYrxpab1qtAMUS2H4PnuVKsHIbIHD2kRXSMqoadv5FisOKMi73BSCx9dOn4o6ZaodgZK8SWkowxTLLQGYn+bckzqJR0RPijf/5YS7Gi+2dWPZ5kjTJRXFbT0UFXL2FHP6d9T3VNf9zzYNWodb2W/gpD40= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=jKH0vpCC; arc=none smtp.client-ip=209.85.214.180 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="jKH0vpCC" Received: by mail-pl1-f180.google.com with SMTP id d9443c01a7336-2350fc2591dso44285085ad.1 for ; Tue, 10 Jun 2025 06:22:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1749561736; x=1750166536; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=klAB2ncfCtZERTrAyu2rbSFj1iTvAJjUvwJYS5sgM+0=; b=jKH0vpCCz1raMyiXndi0YUU1kk+gY6N0QddxJQcXVjSlJPaF3Kl8P4TMkDwBwhXOL+ q5BBbgf7nwcEfUSz+wTQN6DbhNgn4hlPPxlonagpKqDYnsH9EZb0AdFXrIU2ClNBJMvc cPSDpn2NorLzXmwwE8u3zv02pKsYr5szWPHjXkdQVAq1JQyS2C6+GRJlZsd5RvsJevng 5M4jKx82hQHNFM2YTY/UtFDULCTJxadoAqFUHMzALiKIatuMQIyHLv14Pn1SwiMs7TSL J6mbblxZE+Eh50BlJhv1fP8NzKzaVJcJdmc+VXdSxV7lZcqpwFbxkFjoUlIz5XF59fhy b4Xg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749561736; x=1750166536; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=klAB2ncfCtZERTrAyu2rbSFj1iTvAJjUvwJYS5sgM+0=; b=W/GincvA8V6vOlTe1FRyP/wFrUonzqKdgoPYgSu5vS46fci9VOYfT0ZmcAMQk9GrkZ IJosQDPdEoYkDwVgY2a1btnDZVifmsjR1YR/JtmcSKZzgRYytCvAje0ipssHW79wxyPu j0sALCNdZzNJwMngIyPluo/mTe9hctkk9+5x1NIJGU3SPEdDa1odnMZqcN2jlQqhIXjy LTKUTN9gNJJkao6VqbNtF0S8pqrl5bHH0DB1i1759TtAAz6Jbeg1BY3kUIP0+8tlLyh5 jmAeqykx1mSnQ+Wi5LLcVchIFN+AZtyBUEBe6VP34O2s5RBMqZFYWYTVjzU0DsgMsWWh MA5w== X-Forwarded-Encrypted: i=1; AJvYcCURTY0AOodqSRptKArfrAJzV9mSoMkuEZIFXqj3p6EMss7O8UOlfAXZTEaJyBPMXr6QBegEnarPA/oFvFg=@vger.kernel.org X-Gm-Message-State: AOJu0Ywqu3zgIsIr9vH8N15L2Sbg8fp15aVpBuoGtTxiz1TfkaW8ntKo Z0U43FfcKLepzAh3oxzWxA7jt+ilphl1edGnupEmf7iiCoCJQB1Tk26TuFmRrorL0vs= X-Gm-Gg: ASbGncvtElJeQqhDIgjUqO32C2QfUWQAaPLSIejl8Pq6qz+UdcvfL5sSgroG5q58uR6 U0G3OBHnqhc99SrssPWCufA3jCAfeiIzW/Rfmv7Dprb4KpckiZo5g4HeZcimpSK601BHRZypc/c 5qTNLNYiGVXJ2eL99sj/hEP99k6eu2lRKjZlUtnWue4H2KZKVQsvXX1wYgalOShYvwZyvGMN0dI sDUVVsjO0QSKItFDA2MbF8XyvVLuz/MFlj0xlgeA41kiouqRUHUMQ75+Z/iVZZqy4tPzePDqoF2 1KBACDRWMth4cutUuuLSlDQRsHtWxhRe+Pqf8pyXsvDAmpfbCgeKknTu0EHOGzaO/NOsNFr5rQ= = X-Google-Smtp-Source: AGHT+IEqVq8mQti3tRT+eBtluesPlLE/oLnB08dp/lHegWMkSJCFxjWNMm/J+IaFVS/OPUwi9sABqw== X-Received: by 2002:a17:902:ccd0:b0:236:15b7:62e3 with SMTP id d9443c01a7336-23635bb9896mr50735745ad.9.1749561735859; Tue, 10 Jun 2025 06:22:15 -0700 (PDT) Received: from localhost ([122.172.81.72]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-236034061f3sm71537895ad.179.2025.06.10.06.22.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 10 Jun 2025 06:22:15 -0700 (PDT) From: Viresh Kumar To: Boqun Feng , "Rafael J. Wysocki" , Miguel Ojeda , Alex Gaynor , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Thomas Gleixner , Peter Zijlstra Cc: Viresh Kumar , Vincent Guittot , Yury Norov , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH V3 3/3] rust: cpu: Add CpuId::current() to retrieve current CPU ID Date: Tue, 10 Jun 2025 18:51:58 +0530 Message-Id: X-Mailer: git-send-email 2.31.1.272.g89b43f80a514 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Introduce `CpuId::current()`, a constructor that wraps the C function `raw_smp_processor_id()` to retrieve the current CPU identifier without guaranteeing stability. This function should be used only when the caller can ensure that the CPU ID won't change unexpectedly due to preemption or migration. Suggested-by: Boqun Feng Signed-off-by: Viresh Kumar Reviewed-by: Boqun Feng --- MAINTAINERS | 1 + rust/helpers/cpu.c | 8 ++++++++ rust/helpers/helpers.c | 1 + rust/kernel/cpu.rs | 10 ++++++++++ 4 files changed, 20 insertions(+) create mode 100644 rust/helpers/cpu.c diff --git a/MAINTAINERS b/MAINTAINERS index a92290fffa16..4255186784c4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6254,6 +6254,7 @@ F: include/linux/cpuhotplug.h F: include/linux/smpboot.h F: kernel/cpu.c F: kernel/smpboot.* +F: rust/helper/cpu.c F: rust/kernel/cpu.rs =20 CPU IDLE TIME MANAGEMENT FRAMEWORK diff --git a/rust/helpers/cpu.c b/rust/helpers/cpu.c new file mode 100644 index 000000000000..824e0adb19d4 --- /dev/null +++ b/rust/helpers/cpu.c @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include + +unsigned int rust_helper_raw_smp_processor_id(void) +{ + return raw_smp_processor_id(); +} diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c index 0f1b5d115985..16fa9bca5949 100644 --- a/rust/helpers/helpers.c +++ b/rust/helpers/helpers.c @@ -13,6 +13,7 @@ #include "build_assert.c" #include "build_bug.c" #include "clk.c" +#include "cpu.c" #include "cpufreq.c" #include "cpumask.c" #include "cred.c" diff --git a/rust/kernel/cpu.rs b/rust/kernel/cpu.rs index 7549594fad7f..a946c8a9d1a2 100644 --- a/rust/kernel/cpu.rs +++ b/rust/kernel/cpu.rs @@ -102,6 +102,16 @@ pub fn from_u32(id: u32) -> Option { pub fn as_u32(&self) -> u32 { self.0 } + + /// Returns the ID of the CPU the code is currently running on. + /// + /// The returned value is considered unstable because it may change + /// unexpectedly due to preemption or CPU migration. It should only be + /// used when the context ensures that the task remains on the same CP= U. + pub fn current() -> Self { + // SAFETY: raw_smp_processor_id() always returns a valid CPU ID. + unsafe { Self::from_u32_unchecked(bindings::raw_smp_processor_id()= ) } + } } =20 impl From for u32 { --=20 2.31.1.272.g89b43f80a514