From d09142c136c81e190c78a17eac88153ba9464eff Mon Sep 17 00:00:00 2001 From: Aaron Durbin Date: Wed, 14 Dec 2016 15:36:56 -0600 Subject: soc/intel/common: provide option to invalide MRC cache on recovery Allow a board/platform to invalidate the normal MRC cache when hardware retraining is requested in recovery mode. A small 4 byte payload is used to update the latest data written. It will of course fail on MRC cache retreival on next usage. BUG=chrome-os-partner:60592 BRANCH=reef Change-Id: Ic88cd66802664813562d003f50d54e4a4ea375ef Signed-off-by: Aaron Durbin Reviewed-on: https://review.coreboot.org/17870 Tested-by: build bot (Jenkins) Reviewed-by: Duncan Laurie --- src/soc/intel/common/Kconfig | 4 ++++ src/soc/intel/common/mrc_cache.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) (limited to 'src/soc/intel') diff --git a/src/soc/intel/common/Kconfig b/src/soc/intel/common/Kconfig index 1cc856eb5e..68bb38af7a 100644 --- a/src/soc/intel/common/Kconfig +++ b/src/soc/intel/common/Kconfig @@ -31,6 +31,10 @@ config HAS_RECOVERY_MRC_CACHE bool default n +config MRC_CLEAR_NORMAL_CACHE_ON_RECOVERY_RETRAIN + bool + default n + config MRC_SETTINGS_VARIABLE_DATA bool default n diff --git a/src/soc/intel/common/mrc_cache.c b/src/soc/intel/common/mrc_cache.c index 69e5b00de1..e0d4b7de01 100644 --- a/src/soc/intel/common/mrc_cache.c +++ b/src/soc/intel/common/mrc_cache.c @@ -486,6 +486,37 @@ static void protect_mrc_region(void) protect_mrc_cache(DEFAULT_MRC_CACHE); } +static void invalidate_normal_cache(void) +{ + struct region_file cache_file; + struct region_device rdev; + const char *name = DEFAULT_MRC_CACHE; + const uint32_t invalid = ~MRC_DATA_SIGNATURE; + + /* Invalidate only on recovery mode with retraining enabled. */ + if (!vboot_recovery_mode_enabled()) + return; + if (!vboot_recovery_mode_memory_retrain()) + return; + + if (fmap_locate_area_as_rdev_rw(name, &rdev) < 0) { + printk(BIOS_ERR, "MRC: Couldn't find '%s' region. Invalidation failed\n", + name); + return; + } + + if (region_file_init(&cache_file, &rdev) < 0) { + printk(BIOS_ERR, "MRC: region file invalid for '%s'. Invalidation failed\n", + name); + return; + } + + /* Push an update that consists of 4 bytes that is smaller than the + * MRC metadata as well as an invalid signature. */ + if (region_file_update_data(&cache_file, &invalid, sizeof(invalid)) < 0) + printk(BIOS_ERR, "MRC: invalidation failed for '%s'.\n", name); +} + static void update_mrc_cache(void *unused) { update_mrc_cache_by_type(MRC_TRAINING_DATA); @@ -493,6 +524,9 @@ static void update_mrc_cache(void *unused) if (IS_ENABLED(CONFIG_MRC_SETTINGS_VARIABLE_DATA)) update_mrc_cache_by_type(MRC_VARIABLE_DATA); + if (IS_ENABLED(CONFIG_MRC_CLEAR_NORMAL_CACHE_ON_RECOVERY_RETRAIN)) + invalidate_normal_cache(); + protect_mrc_region(); } -- cgit v1.2.3