Message ID | 20200614165958.159716-17-sjg@chromium.org |
---|---|
State | Superseded |
Headers | show |
Series | x86: Enhance MTRR functionality to support multiple CPUs | expand |
Hi Simon, On Mon, Jun 15, 2020 at 1:00 AM Simon Glass <sjg at chromium.org> wrote: > > 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 at chromium.org> > Reviewed-by: Wolfgang Wallner <wolfgang.wallner at br-automation.com> > --- > > Changes in v2: > - Rename function to mtrr_write_all() > > 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 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; > } > > -- We need to find a place where mtrr in BSP is duplicated in AP. Currently this is done in init_cache_f_r() but at that time SMP is not ready yet. Regards, Bin
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; }