x86: mtrr: Update MTRRs on all CPUs
authorSimon Glass <sjg@chromium.org>
Fri, 17 Jul 2020 14:48:25 +0000 (08:48 -0600)
committerBin Meng <bmeng.cn@gmail.com>
Mon, 20 Jul 2020 01:46:47 +0000 (09:46 +0800)
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>
arch/x86/cpu/mtrr.c

index c9b4e7d..5c56755 100644 (file)
@@ -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;
 }