summaryrefslogtreecommitdiff
path: root/arch/x86/cpu
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2020-07-17 17:48:25 +0300
committerBin Meng <bmeng.cn@gmail.com>2020-07-20 04:46:47 +0300
commitaa3a4d870e53e4517320140902eb9488a73e84ce (patch)
tree8d16c7dbe0a8a407c1eb327144ab8b22a4d880c0 /arch/x86/cpu
parent4f58f73d38bb0b367042018ef62bcf6bc095cf44 (diff)
downloadu-boot-aa3a4d870e53e4517320140902eb9488a73e84ce.tar.xz
x86: mtrr: Update MTRRs on all CPUs
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> Reviewed-by: Wolfgang Wallner <wolfgang.wallner@br-automation.com> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Diffstat (limited to 'arch/x86/cpu')
-rw-r--r--arch/x86/cpu/mtrr.c57
1 files changed, 57 insertions, 0 deletions
diff --git a/arch/x86/cpu/mtrr.c b/arch/x86/cpu/mtrr.c
index c9b4e7d06e..5c567551e5 100644
--- a/arch/x86/cpu/mtrr.c
+++ b/arch/x86/cpu/mtrr.c
@@ -74,10 +74,61 @@ void mtrr_read_all(struct mtrr_info *info)
}
}
+void mtrr_write_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 write_mtrrs(void *arg)
+{
+ struct mtrr_info *info = arg;
+
+ mtrr_write_all(info);
+}
+
+static void read_mtrrs(void *arg)
+{
+ struct mtrr_info *info = arg;
+
+ mtrr_read_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, read_mtrrs, &info);
+ if (ret == -ENXIO)
+ return 0;
+ else if (ret)
+ return log_msg_ret("bsp", ret);
+
+ ret = mp_run_on_cpus(MP_SELECT_APS, write_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;
}