From 63fcb4a1f89f1b74f834249b1bc683da280221fa Mon Sep 17 00:00:00 2001 From: Aaron Durbin Date: Thu, 12 Dec 2013 10:29:48 -0800 Subject: baytrail: cache reference code for S3 resume MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to use the same reference code on S3 resume that was booted the program needs to be cached. Piggy back on the ramstage cache to save the loaded reference code program. BUG=chrome-os-partner:22867 BRANCH=None TEST=Built and booted. S3 resumed. Noted locations of reference code caching and load addresses in console. Change-Id: I90ceaf5697e8c269c3244370519d4d8a8ee2eb4a Signed-off-by: Aaron Durbin Reviewed-on: https://chromium-review.googlesource.com/179777 Reviewed-by: Duncan Laurie Reviewed-on: http://review.coreboot.org/5013 Tested-by: build bot (Jenkins) Reviewed-by: Kyösti Mälkki --- src/soc/intel/baytrail/refcode.c | 109 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 101 insertions(+), 8 deletions(-) (limited to 'src/soc') diff --git a/src/soc/intel/baytrail/refcode.c b/src/soc/intel/baytrail/refcode.c index 9b5aa6790e..f746358faf 100644 --- a/src/soc/intel/baytrail/refcode.c +++ b/src/soc/intel/baytrail/refcode.c @@ -17,19 +17,113 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include +#include #include #include #include #include +#include #include #include +static inline int is_s3_resume(void) +{ +#if CONFIG_HAVE_ACPI_RESUME + return acpi_slp_type == 3; +#else + return 0; +#endif +} + +static inline struct ramstage_cache *next_cache(struct ramstage_cache *c) +{ + return (struct ramstage_cache *)&c->program[c->size]; +} + static void ABI_X86 send_to_console(unsigned char b) { console_tx_byte(b); } +static efi_wrapper_entry_t load_refcode_from_cache(void) +{ + struct ramstage_cache *c; + long cache_size; + + printk(BIOS_DEBUG, "refcode loading from cache.\n"); + + c = ramstage_cache_location(&cache_size); + + if (!ramstage_cache_is_valid(c)) { + printk(BIOS_DEBUG, "Invalid ramstage cache descriptor.\n"); + return NULL; + } + + c = next_cache(c); + if (!ramstage_cache_is_valid(c)) { + printk(BIOS_DEBUG, "Invalid refcode cache descriptor.\n"); + return NULL; + } + + printk(BIOS_DEBUG, "Loading cached reference code from 0x%08x(%x)\n", + c->load_address, c->size); + memcpy((void *)c->load_address, &c->program[0], c->size); + + return (efi_wrapper_entry_t)c->entry_point; +} + +static void cache_refcode(const struct rmod_stage_load *rsl) +{ + struct ramstage_cache *c; + long cache_size; + + c = ramstage_cache_location(&cache_size); + + if (!ramstage_cache_is_valid(c)) { + printk(BIOS_DEBUG, "No place to cache reference code.\n"); + return; + } + + /* Determine how much remaining cache available. */ + cache_size -= c->size + sizeof(*c); + + if (cache_size < (sizeof(*c) + cbmem_entry_size(rsl->cbmem_entry))) { + printk(BIOS_DEBUG, "Not enough cache space for ref code.\n"); + return; + } + + c = next_cache(c); + c->magic = RAMSTAGE_CACHE_MAGIC; + c->entry_point = (uint32_t)rsl->entry; + c->load_address = (uint32_t)cbmem_entry_start(rsl->cbmem_entry); + c->size = cbmem_entry_size(rsl->cbmem_entry);; + + printk(BIOS_DEBUG, "Caching refcode at 0x%p(%x)\n", + &c->program[0], c->size); + memcpy(&c->program[0], (void *)c->load_address, c->size); +} + +static efi_wrapper_entry_t load_refcode_from_cbfs(void) +{ + struct rmod_stage_load refcode = { + .cbmem_id = CBMEM_ID_REFCODE, + .name = CONFIG_CBFS_PREFIX "/refcode", + }; + + printk(BIOS_DEBUG, "refcode loading from cbfs.\n"); + + if (rmodule_stage_load_from_cbfs(&refcode) || refcode.entry == NULL) { + printk(BIOS_DEBUG, "Error loading reference code.\n"); + return NULL; + } + + cache_refcode(&refcode); + + return refcode.entry; +} + void baytrail_run_reference_code(void) { int ret; @@ -38,18 +132,17 @@ void baytrail_run_reference_code(void) .version = EFI_WRAPPER_VER, .console_out = send_to_console, }; - struct rmod_stage_load refcode = { - .cbmem_id = CBMEM_ID_REFCODE, - .name = CONFIG_CBFS_PREFIX "/refcode", - }; - if (rmodule_stage_load_from_cbfs(&refcode) || refcode.entry == NULL) { - printk(BIOS_DEBUG, "Error loading reference code.\n"); - return; + if (is_s3_resume()) { + entry = load_refcode_from_cache(); + } else { + entry = load_refcode_from_cbfs(); } + if (entry == NULL) + return; + wrp.tsc_ticks_per_microsecond = tsc_freq_mhz(); - entry = refcode.entry; /* Call into reference code. */ ret = entry(&wrp); -- cgit v1.2.3