cpu/x86: Conditionally invalidate caches based on self-snooping support

The code currently unconditionally flushes or invalidates the entire
cache (using `clflush_region` or `wbinvd`) after loading the SIPI vector
for APs and after loading SMM handlers.

This commit modifies this behavior to only perform these cache
operations if the CPU does *not* support self-snooping.

Self-snooping CPUs can maintain cache coherency within the core/
complex more efficiently. CPU with self-snoop enabled does not
necessarily need to perform wbinvd to ensure data written to the
cache is reflected in main memory. Self-snooping CPUs employ a
write-back caching policy, combined with a cache coherence protocol,
to manage data writes and ensure consistency between cache and main
memory.

When the BSP writes the SIPI vector or SMM handlers to memory, other
units within the same CPU that might be caching these regions should
be aware of the updates through the self-snooping mechanism. A full
cache flush or invalidate to ensure cache contains reaches to main
memory might be unnecessary and could negatively impact performance.

By conditionally performing these cache operations based on
`self_snooping_supported()`, we can optimize the boot process for CPUs
that have advanced cache coherency features while maintaining correct
behavior on older or simpler CPUs.

TEST=Boot google/rex, brox and fatcat with this patch. Able to reduce
boot time by ~19-25ms.

Change-Id: If32439752d0ceaa03b1d81873ea0bc562092e9d5
Signed-off-by: Subrata Banik <subratabanik@google.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/87182
Reviewed-by: Shuo Liu <shuo.liu@intel.com>
Reviewed-by: Jérémy Compostella <jeremy.compostella@intel.com>
Reviewed-by: Kapil Porwal <kapilporwal@google.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Subrata Banik 2025-04-05 08:08:52 +00:00
commit ee9b0fa199
2 changed files with 18 additions and 12 deletions

View file

@ -49,8 +49,10 @@ void arch_segment_loaded(uintptr_t start, size_t size, int flags)
if (!cbmem_online())
return;
if (clflush_supported())
clflush_region(start, size);
else
printk(BIOS_DEBUG, "Not flushing cache to RAM, CLFLUSH not supported\n");
if (!self_snooping_supported()) {
if (clflush_supported())
clflush_region(start, size);
else
printk(BIOS_DEBUG, "Not flushing cache to RAM, CLFLUSH not supported\n");
}
}

View file

@ -365,12 +365,14 @@ static atomic_t *load_sipi_vector(struct mp_params *mp_params)
ap_count = &sp->ap_count;
atomic_set(ap_count, 0);
/* Make sure SIPI data hits RAM so the APs that come up will see the
startup code even if the caches are disabled. */
if (clflush_supported())
clflush_region((uintptr_t)mod_loc, module_size);
else
wbinvd();
if (!self_snooping_supported()) {
/* Make sure SIPI data hits RAM so the APs that come up will see the
startup code even if the caches are disabled. */
if (clflush_supported())
clflush_region((uintptr_t)mod_loc, module_size);
else
wbinvd();
}
return ap_count;
}
@ -826,8 +828,10 @@ static void load_smm_handlers(void)
smm_disable();
}
/* Ensure the SMM handlers hit DRAM before performing first SMI. */
wbinvd();
if (!self_snooping_supported()) {
/* Ensure the SMM handlers hit DRAM before performing first SMI. */
wbinvd();
}
/*
* Indicate that the SMM handlers have been loaded and MP