From nobody Tue Apr 7 18:46:39 2026 Received: from mail-dy1-f170.google.com (mail-dy1-f170.google.com [74.125.82.170]) (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 9863E33D517 for ; Thu, 26 Feb 2026 23:47:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.170 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772149672; cv=none; b=oZA/pw6mhUjtktBDaS2fVRobW88uzwacdcyvptbyz2n6QZNCRyGjHKM8sitrUv84l6uNfo+lOAeo0UI9jqc4syE9lwXt8Z8E+IcoZBmU9NVQ/xYV8ejao925BJgj+bM5BAye4GROprst/xTZ7Ev1DapAtRuz0GQe9MnS3ENOWqE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772149672; c=relaxed/simple; bh=eHSd6gZAgAs99aURB/P61YrQaeqSUqKmTJDHpVJAJgk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=spmgjRHD1nxZHD9T9BWtRC1LKOth+YU6wy45Ce+X2CwsnfogrTbCwkoxNBc5l6QLCV5ADEViWEY0qwtfOmAZvpNIRWfjPpj3zHjBD56eI5gHxidZN4Mi5/Zp8XtlWS+xHnxi2AQO8m9AUP1xrtk8UYMjLuneA+VO1PTfNv0Ssb4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=d1Yj8Xhi; arc=none smtp.client-ip=74.125.82.170 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="d1Yj8Xhi" Received: by mail-dy1-f170.google.com with SMTP id 5a478bee46e88-2bdc47747e2so1217828eec.0 for ; Thu, 26 Feb 2026 15:47:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772149667; x=1772754467; 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=a9Hb2iavLuCFwRbZcUJdleryz74/Q+xg8WkVXrxCwXo=; b=d1Yj8XhiNEDcSEBMYSPG0iltvoIdKiu6FndiVhVCztvqTMN/sLm5yehkw+AbZaL2RT 6gDYQEEdSPjmh7kU9quk2KhOVHvYP4al2ENNvlFxF31NrA9uDeoN/krSBa4Xicaaj3SY FkVkZb1SEh3y7CGEnIH46f+tFbHfFxe8ZfUlmcwXT4oXlMSKtMtcU4i4Ml/HH7dT98nj n20IupGAK7iFGvKdoe79DnElTMpMo3XEDLNxVLlzfCcESZZu1Wm7a58TJxr9q7tapJjy rftfIX6+3GsEq2WEU//+z1iVOZqXpSt7pUvQnYSoVbiNOJgItjQfB+lopPxJJSedmu7k OBIw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772149667; x=1772754467; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=a9Hb2iavLuCFwRbZcUJdleryz74/Q+xg8WkVXrxCwXo=; b=wzRhzmz36rIwqMx6NE67aXV4P4hxCabtG7A9T9RkmdNqC8mzCRO39WGy7Xt6JRJEA8 f4Q7mVrHPUzL5IEBEofL5FiQFg9YM+L9EP/nusDgmcq0SM/dP+byXkB+oby4N0ssZKxV nBV8cR9lFcIMorgde82x4O9vCV2dpDgTY14kJEisHnAeh11i/IjG3qvZ3UpMbSqiRkxw NPAdDpIBk+AQG6qqzwb1oq1niY3fcrsP1xjN+SUI4NRhQZbXxGXGGOQEj7K/FX4yzH8R bDFjLTsOpwz2JxiussciF+/42VIJYveG9a9D7YsdKxoSQPLoGtamH57510h47AJWLDwR hEuQ== X-Forwarded-Encrypted: i=1; AJvYcCWclU2T5rUAzN5/6KLLairwS6w/9iZzN1I7ijA37pf/ENQMdiGv0oGXZUunwrBio7gGhkpSKXj7Iyy2iLw=@vger.kernel.org X-Gm-Message-State: AOJu0YyKcCvPQkTREIsFJr/PteDaFkYcYkPC38WQStzag98igmyg5Y1z qACD7e1z/ZVyR0qBncryjRqjYCz570ui7Rn4d0EDpxaKKrwGMLP14xeb X-Gm-Gg: ATEYQzzBCPo+Aqunbs7FjUdLjafSVvp0R8SVNgCAiGVC2gFfBcHJF4EoknBc82wAuzM QEJQwxUPrPzjGa288w8zrsmBawrcV+oS2/bRGLpVoDvE2//S/0XPdNbVKOM7MTlXGvNVLEirow7 Ec8Zgiu2po8FYAJxy3ReNd8o4lGfB6EU7za+/gNo5SF4srpaTyCs95HlZJHA3g2i+kxbiTatG3I iusjBOsXNmX3sZTWimHkImmJ2mXQBhQmHcFLtUIz6xHr5V+iFDbPwsNasC1EAAPRwvOpy/QS7HY bT204tGC51WFlsQObCxY9U1C3zC1zdzTWSA7WSlrhSs33+3fmYahAs/yMiZhpynhoFE63yJyq6z E/WW2GMa7pv6gfQEcH5mpzkdVxe0uE0p0iZ4FWrvueN3QCm9KZoUYEpG+hXj7Kgs4au+kgoFGo5 T2zHQGcVlmbRPVKF3dB66vAsZN3uTKofRstJGxyjUoRKlCr8Gp878M8OHDGK9Wy3tZfCKvf/937 w== X-Received: by 2002:a05:7300:fb89:b0:2ba:72c3:53c0 with SMTP id 5a478bee46e88-2bde16c8443mr353009eec.0.1772149666732; Thu, 26 Feb 2026 15:47:46 -0800 (PST) Received: from localhost (99-122-55-39.lightspeed.sntcca.sbcglobal.net. [99.122.55.39]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2bdd1bce276sm2849248eec.3.2026.02.26.15.47.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 26 Feb 2026 15:47:46 -0800 (PST) From: Matthew Wood To: Miguel Ojeda , Luis Chamberlain , Petr Pavlu , Daniel Gomez , Sami Tolvanen Cc: Aaron Tomlin , Boqun Feng , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Tamir Duberstein , David Gow , =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= , linux-modules@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 8/8] rust: macros: add configurable initcall levels to module! macro Date: Thu, 26 Feb 2026 15:47:34 -0800 Message-ID: <20260226234736.428341-9-thepacketgeek@gmail.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260226234736.428341-1-thepacketgeek@gmail.com> References: <20260226234736.428341-1-thepacketgeek@gmail.com> 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" Currently all Rust modules using the module! macro are placed at initcall level 6 (device_initcall). Some modules need to initialize earlier in the boot sequence to provide services that other subsystems depend on. Add an InitCallLevel enum representing all eight standard initcall levels (pure through late) and map each to its corresponding .initcallN.init ELF section. Expose this as an optional `initcall` field in the module! macro. When omitted, the default remains level 6 (device) so existing modules are unaffected. Example usage: module! { ... initcall: subsys, } This only affects built-in modules; loadable modules always enter through init_module() regardless of the declared level. Signed-off-by: Matthew Wood --- rust/macros/lib.rs | 4 ++++ rust/macros/module.rs | 56 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs index 83dcc89a425a..cfde59e81cdd 100644 --- a/rust/macros/lib.rs +++ b/rust/macros/lib.rs @@ -135,6 +135,10 @@ /// - `alias`: array of ASCII string literals of the alias names of the = kernel module. /// - `firmware`: array of ASCII string literals of the firmware files of /// the kernel module. +/// - `initcall`: initcall level for built-in modules. Valid values are: +/// `pure` (0), `core` (1), `postcore` (2), `arch` (3), `subsys` (4), +/// `fs` (5), `device` (6, the default), and `late` (7). +/// This only affects built-in modules; loadable modules always use `i= nit_module()`. #[proc_macro] pub fn module(input: TokenStream) -> TokenStream { module::module(parse_macro_input!(input)) diff --git a/rust/macros/module.rs b/rust/macros/module.rs index 4d2e144fa6de..1e210fee4506 100644 --- a/rust/macros/module.rs +++ b/rust/macros/module.rs @@ -436,6 +436,53 @@ macro_rules! parse_ordered_fields { } } =20 +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +enum InitCallLevel { + Pure, + Core, + PostCore, + Arch, + Subsys, + Fs, + Device, + Late, +} + +impl InitCallLevel { + fn section(&self) -> &'static str { + match self { + Self::Pure =3D> ".initcall0.init", + Self::Core =3D> ".initcall1.init", + Self::PostCore =3D> ".initcall2.init", + Self::Arch =3D> ".initcall3.init", + Self::Subsys =3D> ".initcall4.init", + Self::Fs =3D> ".initcall5.init", + Self::Device =3D> ".initcall6.init", + Self::Late =3D> ".initcall7.init", + } + } +} + +impl Parse for InitCallLevel { + fn parse(input: ParseStream<'_>) -> Result { + let ident: Ident =3D input.call(Ident::parse_any)?; + match ident.to_string().as_str() { + "pure" =3D> Ok(Self::Pure), + "core" =3D> Ok(Self::Core), + "postcore" =3D> Ok(Self::PostCore), + "arch" =3D> Ok(Self::Arch), + "subsys" =3D> Ok(Self::Subsys), + "fs" =3D> Ok(Self::Fs), + "device" =3D> Ok(Self::Device), + "late" =3D> Ok(Self::Late), + _ =3D> Err(Error::new_spanned( + ident, + "invalid initcall level. Valid values are: pure, core, pos= tcore, arch, subsys, fs, device, late", + )), + } + } +} + struct Parameter { name: Ident, ptype: Type, @@ -480,6 +527,7 @@ pub(crate) struct ModuleInfo { firmware: Option>, imports_ns: Option>, params: Option>, + initcall: Option, } =20 impl Parse for ModuleInfo { @@ -515,6 +563,7 @@ fn parse(input: ParseStream<'_>) -> Result { braced!(list in input); Punctuated::parse_terminated(&list)? }, + initcall =3D> input.parse()?, ); =20 Ok(ModuleInfo { @@ -527,6 +576,7 @@ fn parse(input: ParseStream<'_>) -> Result { firmware, imports_ns, params, + initcall, }) } } @@ -542,6 +592,7 @@ pub(crate) fn module(info: ModuleInfo) -> Result { firmware, imports_ns, params: _, + initcall, } =3D &info; =20 // Rust does not allow hyphens in identifiers, use underscore instead. @@ -587,7 +638,10 @@ pub(crate) fn module(info: ModuleInfo) -> Result { let ident_init =3D format_ident!("__{ident}_init"); let ident_exit =3D format_ident!("__{ident}_exit"); let ident_initcall =3D format_ident!("__{ident}_initcall"); - let initcall_section =3D ".initcall6.init"; + let initcall_section =3D initcall + .as_ref() + .unwrap_or(&InitCallLevel::Device) + .section(); =20 let global_asm =3D format!( r#".section "{initcall_section}", "a" --=20 2.52.0