
When the boot CPU MTRRs are updated, perform the same update on all other CPUs so they are kept in sync.
This avoids kernel warnings about mismatched MTRRs.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/mtrr.c | 57 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+)
diff --git a/arch/x86/cpu/mtrr.c b/arch/x86/cpu/mtrr.c index 11f3ef08172..a48c9d8232e 100644 --- a/arch/x86/cpu/mtrr.c +++ b/arch/x86/cpu/mtrr.c @@ -74,10 +74,61 @@ void mtrr_save_all(struct mtrr_info *info) } }
+void mtrr_load_all(struct mtrr_info *info) +{ + struct mtrr_state state; + int i; + + for (i = 0; i < MTRR_COUNT; i++) { + mtrr_open(&state, true); + wrmsrl(MTRR_PHYS_BASE_MSR(i), info->mtrr[i].base); + wrmsrl(MTRR_PHYS_MASK_MSR(i), info->mtrr[i].mask); + mtrr_close(&state, true); + } +} + +static void save_mtrrs(void *arg) +{ + struct mtrr_info *info = arg; + + mtrr_save_all(info); +} + +static void load_mtrrs(void *arg) +{ + struct mtrr_info *info = arg; + + mtrr_load_all(info); +} + +/** + * mtrr_copy_to_aps() - Copy the MTRRs from the boot CPU to other CPUs + * + * @return 0 on success, -ve on failure + */ +static int mtrr_copy_to_aps(void) +{ + struct mtrr_info info; + int ret; + + ret = mp_run_on_cpus(MP_SELECT_BSP, save_mtrrs, &info); + if (ret == -ENXIO) + return 0; + else if (ret) + return log_msg_ret("bsp", ret); + + ret = mp_run_on_cpus(MP_SELECT_APS, load_mtrrs, &info); + if (ret) + return log_msg_ret("bsp", ret); + + return 0; +} + int mtrr_commit(bool do_caches) { struct mtrr_request *req = gd->arch.mtrr_req; struct mtrr_state state; + int ret; int i;
debug("%s: enabled=%d, count=%d\n", __func__, gd->arch.has_mtrr, @@ -99,6 +150,12 @@ int mtrr_commit(bool do_caches) mtrr_close(&state, do_caches); debug("mtrr done\n");
+ if (gd->flags & GD_FLG_RELOC) { + ret = mtrr_copy_to_aps(); + if (ret) + return log_msg_ret("copy", ret); + } + return 0; }