baytrail: implement alternative payload loading

Similarly to lynxpoint payload loading can be made faster
by taking advantage of the spi controller's caching and prefetching.
Provide the same mechanism as lynxpoint to provide a 30ms
payload loading savings. The speed up isn't as dramatic as lynxpoint
presumably because baytrail is an SoC without the DMI communication
overhead. Regardless, payload loading decreases from ~55ms to ~25ms.

BUG=chrome-os-partner:25385
BRANCH=baytrail
TEST=Built and did numerous reboots. Observe time savings.

Change-Id: I5726d41559a8b4facb4bfdb7e629d04819dc9d37
Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/184853
Reviewed-by: Duncan Laurie <dlaurie@chromium.org>
This commit is contained in:
Aaron Durbin 2014-02-04 10:24:34 -06:00 committed by chrome-internal-fetch
commit 96722f750a
3 changed files with 104 additions and 0 deletions

View file

@ -8,6 +8,7 @@ if SOC_INTEL_BAYTRAIL
config CPU_SPECIFIC_OPTIONS
def_bool y
select ALT_CBFS_LOAD_PAYLOAD
select CACHE_MRC_SETTINGS
select CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM
select CACHE_ROM

View file

@ -51,6 +51,7 @@ romstage-y += stage_cache.c
ramstage-$(CONFIG_ELOG) += elog.c
ramstage-y += hda.c
ramstage-y += hda_verb.c
ramstage-$(CONFIG_ALT_CBFS_LOAD_PAYLOAD) += spi_loading.c
# Remove as ramstage gets fleshed out
ramstage-y += placeholders.c

View file

@ -0,0 +1,102 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 Google Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdlib.h>
#include <string.h>
#include <arch/byteorder.h>
#include <cbmem.h>
#include <cbfs.h>
#include <console/console.h>
#include <cpu/x86/smm.h>
#include <vendorcode/google/chromeos/chromeos.h>
#define CACHELINE_SIZE 64
#define INTRA_CACHELINE_MASK (CACHELINE_SIZE - 1)
#define CACHELINE_MASK (~INTRA_CACHELINE_MASK)
/*
* Mirror the payload file to the default SMM location if it is small enough.
* The default SMM region can be used since no one is using the memory at this
* location at this stage in the boot.
*/
static inline void *spi_mirror(void *file_start, int file_len)
{
int alignment_diff;
char *src;
char *dest = (void *)SMM_DEFAULT_BASE;
alignment_diff = (INTRA_CACHELINE_MASK & (long)file_start);
/*
* Adjust file length so that the start and end points are aligned to a
* cacheline. Coupled with the ROM caching in the CPU the SPI hardware
* will read and cache full length cachelines. It will also prefetch
* data as well. Once things are mirrored in memory all accesses should
* hit the CPUs cache.
*/
file_len += alignment_diff;
file_len = ALIGN(file_len, CACHELINE_SIZE);
printk(BIOS_DEBUG, "Payload aligned size: 0x%x\n", file_len);
/*
* Just pass back the pointer to ROM space if the file is larger
* than the RAM mirror region.
*/
if (file_len > SMM_DEFAULT_SIZE)
return file_start;
src = (void *)(CACHELINE_MASK & (long)file_start);
/*
* Note that if mempcy is not using 32-bit moves the performance will
* degrade because the SPI hardware prefetchers look for
* cacheline-aligned 32-bit accesses to kick in.
*/
memcpy(dest, src, file_len);
/* Provide pointer into mirrored space. */
return &dest[alignment_diff];
}
void *cbfs_load_payload(struct cbfs_media *media, const char *name)
{
int file_len;
void *file_start;
struct cbfs_file *file;
file_start = vboot_get_payload(&file_len);
if (file_start != NULL)
return spi_mirror(file_start, file_len);
file = cbfs_get_file(media, name);
if (file == NULL)
return NULL;
if (ntohl(file->type) != CBFS_TYPE_PAYLOAD)
return NULL;
file_len = ntohl(file->len);
file_start = CBFS_SUBHEADER(file);
return spi_mirror(file_start, file_len);
}