[U-Boot] [PATCH 085/126] x86: Update mrccache to support multiple caches
Bin Meng
bmeng.cn at gmail.com
Thu Oct 10 07:39:10 UTC 2019
Hi Simon,
On Wed, Sep 25, 2019 at 10:59 PM Simon Glass <sjg at chromium.org> wrote:
>
> With apollolake we need to support a normal cache, which almost never
> changes and a much smaller 'variable' cache which changes every time.
>
> Update the code to add a cache type, use an array for the caches and use a
> for loop to iterate over the caches.
>
> Signed-off-by: Simon Glass <sjg at chromium.org>
> ---
>
> arch/x86/cpu/broadwell/sdram.c | 8 ++-
> arch/x86/cpu/ivybridge/sdram.c | 8 ++-
> arch/x86/cpu/quark/dram.c | 8 ++-
> arch/x86/include/asm/global_data.h | 21 +++++--
> arch/x86/include/asm/mrccache.h | 11 +++-
> arch/x86/lib/fsp/fsp_common.c | 2 +-
> arch/x86/lib/fsp1/fsp_dram.c | 8 ++-
> arch/x86/lib/mrccache.c | 93 ++++++++++++++++++++----------
> 8 files changed, 109 insertions(+), 50 deletions(-)
>
> diff --git a/arch/x86/cpu/broadwell/sdram.c b/arch/x86/cpu/broadwell/sdram.c
> index b31d78c092a..107c04691b0 100644
> --- a/arch/x86/cpu/broadwell/sdram.c
> +++ b/arch/x86/cpu/broadwell/sdram.c
> @@ -82,7 +82,7 @@ static int prepare_mrc_cache(struct pei_data *pei_data)
> struct mrc_region entry;
> int ret;
>
> - ret = mrccache_get_region(NULL, &entry);
> + ret = mrccache_get_region(MRC_TYPE_NORMAL, NULL, &entry);
> if (ret)
> return ret;
> mrc_cache = mrccache_find_current(&entry);
> @@ -168,12 +168,14 @@ int dram_init(void)
> pei_data->data_to_save);
> /* S3 resume: don't save scrambler seed or MRC data */
> if (pei_data->boot_mode != SLEEP_STATE_S3) {
> + struct mrc_output *mrc = &gd->arch.mrc[MRC_TYPE_NORMAL];
> +
> /*
> * This will be copied to SDRAM in reserve_arch(), then written
> * to SPI flash in mrccache_save()
> */
> - gd->arch.mrc_output = (char *)pei_data->data_to_save;
> - gd->arch.mrc_output_len = pei_data->data_to_save_size;
> + mrc->buf = (char *)pei_data->data_to_save;
> + mrc->len = pei_data->data_to_save_size;
> }
> gd->arch.pei_meminfo = pei_data->meminfo;
>
> diff --git a/arch/x86/cpu/ivybridge/sdram.c b/arch/x86/cpu/ivybridge/sdram.c
> index 8a58d0383d5..8b03406666e 100644
> --- a/arch/x86/cpu/ivybridge/sdram.c
> +++ b/arch/x86/cpu/ivybridge/sdram.c
> @@ -115,7 +115,7 @@ static int prepare_mrc_cache(struct pei_data *pei_data)
> ret = read_seed_from_cmos(pei_data);
> if (ret)
> return ret;
> - ret = mrccache_get_region(NULL, &entry);
> + ret = mrccache_get_region(MRC_TYPE_NORMAL, NULL, &entry);
> if (ret)
> return ret;
> mrc_cache = mrccache_find_current(&entry);
> @@ -537,12 +537,14 @@ int dram_init(void)
>
> /* S3 resume: don't save scrambler seed or MRC data */
> if (pei_data->boot_mode != PEI_BOOT_RESUME) {
> + struct mrc_output *mrc = &gd->arch.mrc[MRC_TYPE_NORMAL];
> +
> /*
> * This will be copied to SDRAM in reserve_arch(), then written
> * to SPI flash in mrccache_save()
> */
> - gd->arch.mrc_output = (char *)pei_data->mrc_output;
> - gd->arch.mrc_output_len = pei_data->mrc_output_len;
> + mrc->buf = (char *)pei_data->mrc_output;
> + mrc->len = pei_data->mrc_output_len;
> ret = write_seeds_to_cmos(pei_data);
> if (ret)
> debug("Failed to write seeds to CMOS: %d\n", ret);
> diff --git a/arch/x86/cpu/quark/dram.c b/arch/x86/cpu/quark/dram.c
> index 51f9659ab15..3994355112b 100644
> --- a/arch/x86/cpu/quark/dram.c
> +++ b/arch/x86/cpu/quark/dram.c
> @@ -22,7 +22,7 @@ static __maybe_unused int prepare_mrc_cache(struct mrc_params *mrc_params)
> struct mrc_region entry;
> int ret;
>
> - ret = mrccache_get_region(NULL, &entry);
> + ret = mrccache_get_region(MRC_TYPE_NORMAL, NULL, &entry);
> if (ret)
> return ret;
>
> @@ -152,9 +152,11 @@ int dram_init(void)
> #ifdef CONFIG_ENABLE_MRC_CACHE
> cache = malloc(sizeof(struct mrc_timings));
> if (cache) {
> + struct mrc_output *mrc = &gd->arch.mrc[MRC_TYPE_NORMAL];
> +
> memcpy(cache, &mrc_params.timings, sizeof(struct mrc_timings));
> - gd->arch.mrc_output = cache;
> - gd->arch.mrc_output_len = sizeof(struct mrc_timings);
> + mrc->buf = cache;
> + mrc->len = sizeof(struct mrc_timings);
> }
> #endif
>
> diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h
> index c5faac5c901..2475b3427e1 100644
> --- a/arch/x86/include/asm/global_data.h
> +++ b/arch/x86/include/asm/global_data.h
> @@ -67,6 +67,21 @@ struct mtrr_request {
> uint64_t size;
> };
>
> +/**
> + * struct mrc_output - holds the MRC data
> + *
> + * @buf: MRC training data to save for the next boot. This is set to point to
> + * the raw data after SDRAM init is complete. Then mrccache_setup()
> + * turns it into a proper cache record with a checksum
> + * @len: Length of @buf
> + * @cache: Resulting cache record
> + */
> +struct mrc_output {
> + char *buf;
> + uint len;
> + struct mrc_data_container *cache;
> +};
> +
> /* Architecture-specific global data */
> struct arch_global_data {
> u64 gdt[X86_GDT_NUM_ENTRIES] __aligned(16);
> @@ -90,10 +105,8 @@ struct arch_global_data {
> struct mtrr_request mtrr_req[MAX_MTRR_REQUESTS];
> int mtrr_req_count;
> int has_mtrr;
> - /* MRC training data to save for the next boot */
> - char *mrc_output;
> - unsigned int mrc_output_len;
> - struct mrc_data_container *mrc_cache;
> + /* MRC training data */
> + struct mrc_output mrc[MRC_TYPE_COUNT];
> ulong table; /* Table pointer from previous loader */
> int turbo_state; /* Current turbo state */
> struct irq_routing_table *pirq_routing_table;
> diff --git a/arch/x86/include/asm/mrccache.h b/arch/x86/include/asm/mrccache.h
> index abf58182237..b81e2b2fb6a 100644
> --- a/arch/x86/include/asm/mrccache.h
> +++ b/arch/x86/include/asm/mrccache.h
> @@ -27,6 +27,13 @@ struct mrc_region {
> u32 length;
> };
>
> +/* Types of MRC data */
> +enum mrc_type_t {
> + MRC_TYPE_NORMAL,
> +
> + MRC_TYPE_COUNT,
> +};
> +
> struct udevice;
>
> /**
> @@ -84,6 +91,7 @@ int mrccache_reserve(void);
> * triggers PCI bus enumeration during which insufficient memory issue
> * might be exposed and it causes subsequent SPI flash probe fails).
> *
> + * @type: Type of MRC data to use
> * @devp: Returns pointer to the SPI flash device
> * @entry: Position and size of MRC cache in SPI flash
> * @return 0 if success, -ENOENT if SPI flash node does not exist in the
> @@ -91,7 +99,8 @@ int mrccache_reserve(void);
> * tree, -EINVAL if MRC region properties format is incorrect, other error
> * if SPI flash probe failed.
> */
> -int mrccache_get_region(struct udevice **devp, struct mrc_region *entry);
> +int mrccache_get_region(enum mrc_type_t type, struct udevice **devp,
> + struct mrc_region *entry);
>
> /**
> * mrccache_save() - save MRC data to the SPI flash
> diff --git a/arch/x86/lib/fsp/fsp_common.c b/arch/x86/lib/fsp/fsp_common.c
> index 40ba866d77c..c1c30ce0eb6 100644
> --- a/arch/x86/lib/fsp/fsp_common.c
> +++ b/arch/x86/lib/fsp/fsp_common.c
> @@ -63,7 +63,7 @@ void *fsp_prepare_mrc_cache(void)
> struct mrc_region entry;
> int ret;
>
> - ret = mrccache_get_region(NULL, &entry);
> + ret = mrccache_get_region(MRC_TYPE_NORMAL, NULL, &entry);
> if (ret)
> return NULL;
>
> diff --git a/arch/x86/lib/fsp1/fsp_dram.c b/arch/x86/lib/fsp1/fsp_dram.c
> index 6a3349b42af..5ef89744b94 100644
> --- a/arch/x86/lib/fsp1/fsp_dram.c
> +++ b/arch/x86/lib/fsp1/fsp_dram.c
> @@ -15,9 +15,11 @@ int dram_init(void)
> if (ret)
> return ret;
>
> - if (IS_ENABLED(CONFIG_ENABLE_MRC_CACHE))
> - gd->arch.mrc_output = fsp_get_nvs_data(gd->arch.hob_list,
> - &gd->arch.mrc_output_len);
> + if (IS_ENABLED(CONFIG_ENABLE_MRC_CACHE)) {
> + struct mrc_output *mrc = &gd->arch.mrc[MRC_TYPE_NORMAL];
> +
> + mrc->buf = fsp_get_nvs_data(gd->arch.hob_list, &mrc->len);
> + }
>
> return 0;
> }
> diff --git a/arch/x86/lib/mrccache.c b/arch/x86/lib/mrccache.c
> index 0208696c834..8de7dc48f44 100644
> --- a/arch/x86/lib/mrccache.c
> +++ b/arch/x86/lib/mrccache.c
> @@ -159,44 +159,51 @@ int mrccache_update(struct udevice *sf, struct mrc_region *entry,
> cur);
> if (ret) {
> debug("Failed to write to SPI flash\n");
> - return ret;
> + return log_msg_ret("Cannot update mrccache", ret);
This line change should be in patch [84/126] "x86: Tidy up error
handling in mrccache_save()"
> }
>
> return 0;
> }
>
> -static void mrccache_setup(void *data)
> +static void mrccache_setup(struct mrc_output *mrc, void *data)
> {
> struct mrc_data_container *cache = data;
> u16 checksum;
>
> cache->signature = MRC_DATA_SIGNATURE;
> - cache->data_size = gd->arch.mrc_output_len;
> - checksum = compute_ip_checksum(gd->arch.mrc_output, cache->data_size);
> + cache->data_size = mrc->len;
> + checksum = compute_ip_checksum(mrc->buf, cache->data_size);
> debug("Saving %d bytes for MRC output data, checksum %04x\n",
> cache->data_size, checksum);
> cache->checksum = checksum;
> cache->reserved = 0;
> - memcpy(cache->data, gd->arch.mrc_output, cache->data_size);
> + memcpy(cache->data, mrc->buf, cache->data_size);
>
> - gd->arch.mrc_cache = cache;
> + mrc->cache = cache;
> }
>
> int mrccache_reserve(void)
> {
> - if (!gd->arch.mrc_output_len)
> - return 0;
> + int i;
> +
> + for (i = 0; i < MRC_TYPE_COUNT; i++) {
> + struct mrc_output *mrc = &gd->arch.mrc[i];
>
> - /* adjust stack pointer to store pure cache data plus the header */
> - gd->start_addr_sp -= (gd->arch.mrc_output_len + MRC_DATA_HEADER_SIZE);
> - mrccache_setup((void *)gd->start_addr_sp);
> + if (!mrc->len)
> + continue;
>
> - gd->start_addr_sp &= ~0xf;
> + /* adjust stack pointer to store pure cache data plus header */
> + gd->start_addr_sp -= (mrc->len + MRC_DATA_HEADER_SIZE);
> + mrccache_setup(mrc, (void *)gd->start_addr_sp);
> +
> + gd->start_addr_sp &= ~0xf;
> + }
>
> return 0;
> }
>
> -int mrccache_get_region(struct udevice **devp, struct mrc_region *entry)
> +int mrccache_get_region(enum mrc_type_t type, struct udevice **devp,
> + struct mrc_region *entry)
> {
> struct udevice *dev;
> ofnode mrc_node;
> @@ -221,7 +228,8 @@ int mrccache_get_region(struct udevice **devp, struct mrc_region *entry)
> }
>
> /* Find the place where we put the MRC cache */
> - mrc_node = dev_read_subnode(dev, "rw-mrc-cache");
> + mrc_node = dev_read_subnode(dev, type == MRC_TYPE_NORMAL ?
> + "rw-mrc-cache" : "rw-var-mrc-cache");
This change should either be put in next patch [86/126] "x86: Add
mrccache support for a 'variable' cache", or squash the [86/126] patch
into this patch.
> if (!ofnode_valid(mrc_node))
> return log_msg_ret("Cannot find node", -EPERM);
>
> @@ -233,31 +241,33 @@ int mrccache_get_region(struct udevice **devp, struct mrc_region *entry)
>
> if (devp)
> *devp = dev;
> - debug("MRC cache in '%s', offset %x, len %x, base %x\n",
> - dev->name, entry->offset, entry->length, entry->base);
> + debug("MRC cache type %d in '%s', offset %x, len %x, base %x\n",
> + type, dev->name, entry->offset, entry->length, entry->base);
>
> return 0;
> }
>
> -int mrccache_save(void)
> +static int mrccache_save_type(enum mrc_type_t type)
> {
> struct mrc_data_container *cache;
> + struct mrc_output *mrc;
> struct mrc_region entry;
> struct udevice *sf;
> int ret;
>
> - if (!gd->arch.mrc_output_len)
> + mrc = &gd->arch.mrc[type];
> + if (!mrc->len)
> return 0;
> - debug("Saving %#x bytes of MRC output data to SPI flash\n",
> - gd->arch.mrc_output_len);
> -
> - ret = mrccache_get_region(&sf, &entry);
> + log_debug("Saving %#x bytes of MRC output data type %d to SPI flash\n",
> + mrc->len, type);
> + ret = mrccache_get_region(type, &sf, &entry);
> if (ret)
> return log_msg_ret("Cannot get region", ret);
> ret = device_probe(sf);
> if (ret)
> return log_msg_ret("Cannot probe device", ret);
> - cache = gd->arch.mrc_cache;
> + cache = mrc->cache;
> +
> ret = mrccache_update(sf, &entry, cache);
> if (!ret)
> debug("Saved MRC data with checksum %04x\n", cache->checksum);
> @@ -267,17 +277,36 @@ int mrccache_save(void)
> return 0;
> }
>
> +int mrccache_save(void)
> +{
> + int i;
> +
> + for (i = 0; i < MRC_TYPE_COUNT; i++) {
> + int ret;
> +
> + ret = mrccache_save_type(i);
> + if (ret)
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> int mrccache_spl_save(void)
> {
> - void *data;
> - int size;
> -
> - size = gd->arch.mrc_output_len + MRC_DATA_HEADER_SIZE;
> - data = malloc(size);
> - if (!data)
> - return log_msg_ret("Allocate MRC cache block", -ENOMEM);
> - mrccache_setup(data);
> - gd->arch.mrc_output = data;
> + int i;
> +
> + for (i = 0; i < MRC_TYPE_COUNT; i++) {
> + struct mrc_output *mrc = &gd->arch.mrc[i];
> + void *data;
> + int size;
> +
> + size = mrc->len + MRC_DATA_HEADER_SIZE;
> + data = malloc(size);
> + if (!data)
> + return log_msg_ret("Allocate MRC cache block", -ENOMEM);
> + mrccache_setup(mrc, data);
> + }
>
> return mrccache_save();
> }
> --
Regards,
Bin
More information about the U-Boot
mailing list