Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions drivers/gpu/drm/asahi/fwid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,8 +254,13 @@ mod tests {
else {
panic!("T6041 must identify its loaded firmware");
};
assert_eq!(builds.len(), 2);
for (i, build) in builds.iter().enumerate() {
assert_eq!(builds.len(), 3);
// The last two admit the 25G83 images, with the 40- and the 32-core configuration.
assert_eq!(builds[1].images.len(), builds[2].images.len());
for (a, b) in builds[1].images.iter().zip(builds[2].images) {
assert_eq!((a.entropy, a.text_sha256), (b.entropy, b.text_sha256));
}
for (i, build) in builds[..2].iter().enumerate() {
let other = &builds[1 - i];
for image in build.images {
let (entropy, digest) = (image.entropy, image.text_sha256);
Expand All @@ -277,6 +282,10 @@ mod tests {
let cores = crate::hw::t6041::CONFIG.core_layout.cores;
assert_eq!(g83.core_layout.cores, cores);
assert_eq!(cores, Some((4, 40)));
let g83_32 = builds[2].config.unwrap();
assert_eq!(g83_32.core_layout.cores, Some((4, 32)));
assert!(g83_32.reserved_slots.is_empty());
assert_eq!(g83_32.windows.len(), map.len());
}

#[cfg(CONFIG_DRM_ASAHI_G16)]
Expand Down
11 changes: 8 additions & 3 deletions drivers/gpu/drm/asahi/g17/fw/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1629,13 +1629,18 @@ mod ta_mode_tests {
}
}

/// The variants of the builds T6041 admits: 25F84, then 25G83.
/// The variants of the builds T6041 admits: 25F84, then 25G83, which the 40- and the
/// 32-core configurations run with the same rules.
fn t6041_variants() -> [&'static Variant; 2] {
let Firmware::Identified(builds) = crate::hw::t6041::CONFIG.firmware else {
panic!("T6041 must identify its loaded firmware");
};
assert_eq!(builds.len(), 2);
[builds[0].variant, builds[1].variant]
assert_eq!(builds.len(), 3);
let (g83, g83_32) = (builds[1].variant, builds[2].variant);
assert_eq!(g83.ta_mode_1, g83_32.ta_mode_1);
assert_eq!(g83.compute, g83_32.compute);
assert_eq!(g83.programs, g83_32.programs);
[builds[0].variant, g83]
}

/// The TA mode of every admitted T6041 build.
Expand Down
34 changes: 28 additions & 6 deletions drivers/gpu/drm/asahi/g17/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1173,10 +1173,12 @@ impl Gpu {
} else {
None
};
let (variant, build_cfg) = Self::firmware_variant(dev, &cfg.firmware)?;
let id = regs.get_g17_id()?;
let active_cores: u32 = id.core_masks.iter().map(|mask| mask.count_ones()).sum();
let (variant, build_cfg) =
Self::firmware_variant(dev, &cfg.firmware, (id.num_clusters, active_cores))?;
// A build with its own configuration of the SoC runs with that one.
let cfg = build_cfg.unwrap_or(cfg);
let id = regs.get_g17_id()?;
if let Some(calibration) = calibration {
calibration.check_cores(&id.core_masks)?;
calibration.check_opps(&initdata::InitData::opps(dev, cfg.opps, id.num_clusters)?)?;
Expand Down Expand Up @@ -1216,7 +1218,6 @@ impl Gpu {
let renders = availability::Availability::new()?;
let reclaim = runtime::teardown::ReclaimBatch::new()?;
let feed = feed::Feed::new()?;
let active_cores = id.core_masks.iter().map(|mask| mask.count_ones()).sum();
let alternate = cfg.core_layout.cores.is_some_and(|(clusters, cores)| {
clusters == id.num_clusters
&& cores != active_cores
Expand Down Expand Up @@ -1329,9 +1330,15 @@ impl Gpu {
/// Returns the variant of the loaded firmware build and the configuration it runs with, if
/// it has its own. An identified SoC refuses a build it does not know, before anything is
/// written to the GPU.
///
/// Builds can admit the same image with configurations measured on different core layouts.
/// The first identified build whose configuration admits `cores` (clusters and enabled
/// cores, as probed) is chosen, else the first identified one, whose core check then
/// refuses the GPU.
fn firmware_variant(
dev: &AsahiDrmDevice,
firmware: &fw::variant::Firmware,
cores: (u32, u32),
) -> Result<(&'static fw::Variant, Option<&'static Config>)> {
let builds = match firmware {
fw::variant::Firmware::Fixed(variant) => return Ok((variant, None)),
Expand All @@ -1346,11 +1353,26 @@ impl Gpu {
let others = builds
.iter()
.filter(|build| Some(build.os_version) != version);
let mut identified = None;
for build in Iterator::chain(preferred, others) {
if Self::identify_image(dev, build).is_ok() {
dev_info!(dev.as_ref(), "GPU firmware: {}\n", build.name);
return Ok((build.variant, build.config));
if Self::identify_image(dev, build).is_err() {
continue;
}
let admits = build.config.is_none_or(|config| {
config
.core_layout
.cores
.is_none_or(|measured| measured == cores)
});
if admits {
identified = Some(build);
break;
}
identified.get_or_insert(build);
}
if let Some(build) = identified {
dev_info!(dev.as_ref(), "GPU firmware: {}\n", build.name);
return Ok((build.variant, build.config));
}
dev_err!(
dev.as_ref(),
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/asahi/hw/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub(crate) mod t600x;
pub(crate) mod t602x;
pub(crate) mod t6040;
pub(crate) mod t6041;
mod t6041_25g83;
mod t604x;
pub(crate) mod t8103;
pub(crate) mod t8112;
Expand Down
26 changes: 17 additions & 9 deletions drivers/gpu/drm/asahi/hw/t6041.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ use crate::hw::{GpuGen, GpuVariant};
use super::t604x::{instances, window};
use crate::mmu::UatQuirks;

/// What the configurations of both firmware builds share: the 40-core M4 Max measured with
/// 25F84. Only the register map is the build's own.
const BASE: Config = Config {
/// What the configurations of the firmware builds share: the 40-core M4 Max measured with
/// 25F84. The 40-core 25G83 configuration only has its own register map.
pub(super) const BASE: Config = Config {
chip_id: CHIP_ID,
identity: Identity {
family: 0xa,
Expand Down Expand Up @@ -58,18 +58,26 @@ const BASE: Config = Config {
},
};

/// The 40-core M4 Max. 25F84 runs this configuration; 25G83 runs [`CONFIG_25G83`].
/// The 40-core M4 Max. 25F84 runs this configuration; 25G83 runs [`CONFIG_25G83`], or
/// [`super::t6041_25g83::CONFIG`] on a 32-core part.
pub(crate) const CONFIG: Config = Config {
firmware: fw::variant::Firmware::Identified(&BUILDS),
..BASE
};

const BUILDS: [fw::variant::Build; 2] = [
/// The 25G83 image is admitted twice, with the configuration of each measured core layout;
/// the one that matches the probed cores is used.
const BUILDS: [fw::variant::Build; 3] = [
BUILD_25F84,
fw::variant::Build {
config: Some(&CONFIG_25G83),
..BUILD_25G83
},
fw::variant::Build {
name: "macOS 26.6.2 (25G83, iBoot mBoot-18000.161.10), 32 cores",
config: Some(&super::t6041_25g83::CONFIG),
..BUILD_25G83
},
];

const BUILD_25F84: fw::variant::Build = fw::variant::Build {
Expand All @@ -96,9 +104,9 @@ const BUILD_25F84: fw::variant::Build = fw::variant::Build {

/// The macOS 26.6.2 boot firmware (iBoot mBoot-18000.161.10) loads the 25G83 build the M4 Pro
/// runs. iBoot fills part of the loaded TEXT for each Mac, so each admitted image is a
/// measurement. The one listed is the only T6041 image measured so far, on a 32-core J616C
/// (linux#1050); there the core count check of [`CONFIG_25G83`] refuses the GPU.
const BUILD_25G83: fw::variant::Build = fw::variant::Build {
/// measurement. The one listed is the only T6041 image measured so far, on a 32-core J616C,
/// which runs it with [`super::t6041_25g83::CONFIG`].
pub(super) const BUILD_25G83: fw::variant::Build = fw::variant::Build {
os_version: [26, 6, 2],
name: "macOS 26.6.2 (25G83, iBoot mBoot-18000.161.10)",
images: &[crate::fwid::FirmwareBuild {
Expand Down Expand Up @@ -252,7 +260,7 @@ const _: () = {

const MAX_POWER_MW: u32 = 129_702;

const REGION_C: RegionCConfig = RegionCConfig {
pub(super) const REGION_C: RegionCConfig = RegionCConfig {
unk_54: 0x0fa0,
unk_78: [1, 0, 0],
max_power_mw: MAX_POWER_MW,
Expand Down
Loading
Loading