aboutsummaryrefslogtreecommitdiff
path: root/src/arch
diff options
context:
space:
mode:
authorArthur Heymans <arthur@aheymans.xyz>2021-05-14 13:19:43 +0200
committerArthur Heymans <arthur@aheymans.xyz>2022-05-16 07:05:03 +0000
commit46b409da483ebfc8d9c868c713f5ad68b62c808e (patch)
treef6fd02685ea558df7447dc3449d3fba787c09183 /src/arch
parent645dde77940d12979166555b17dbc81cda1bc48b (diff)
arch/x86/postcar: Set up postcar MTRR in C code
Setting up postcar MTRRs is done when invd is already called so there is no reason to do this in assembly anymore. This also drops the custom code for Quark to set up MTRRs. TESTED on foxconn/g41m and hermes/prodrive that MTRR are properly set in postcar & ramstage. Change-Id: I5ec10e84118197a04de0a5194336ef8bb049bba4 Signed-off-by: Arthur Heymans <arthur@aheymans.xyz> Reviewed-on: https://review.coreboot.org/c/coreboot/+/54299 Reviewed-by: Elyes Haouas <ehaouas@noos.fr> Reviewed-by: Raul Rangel <rrangel@chromium.org> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Diffstat (limited to 'src/arch')
-rw-r--r--src/arch/x86/exit_car.S126
-rw-r--r--src/arch/x86/include/arch/romstage.h8
-rw-r--r--src/arch/x86/postcar_loader.c83
3 files changed, 27 insertions, 190 deletions
diff --git a/src/arch/x86/exit_car.S b/src/arch/x86/exit_car.S
index d3954d365f..a83765ba92 100644
--- a/src/arch/x86/exit_car.S
+++ b/src/arch/x86/exit_car.S
@@ -4,37 +4,6 @@
#include <cpu/x86/cr.h>
#include <cpu/x86/cache.h>
-.section ".module_parameters", "aw", @progbits
-/* stack_top indicates the stack to pull MTRR information from. */
-.global post_car_stack_top
-post_car_stack_top:
-.long 0
-.long 0
-
-#if ENV_X86_64
-.code64
-.macro pop_eax_edx
- pop %rax
- mov %rax, %rdx
- shr $32, %rdx
-.endm
-.macro pop_ebx_esi
- pop %rbx
- mov %rbx, %rsi
- shr $32, %rsi
-.endm
-#else
-.code32
-.macro pop_eax_edx
- pop %eax
- pop %edx
-.endm
-.macro pop_ebx_esi
- pop %ebx
- pop %esi
-.endm
-#endif
-
/* Place the stack in the bss section. It's not necessary to define it in the
* the linker script. */
.section .bss, "aw", @nobits
@@ -89,107 +58,22 @@ skip_clflush:
mov %cr0, %rax
and $(~(CR0_CD | CR0_NW)), %eax
mov %rax, %cr0
-
- /* Ensure cache is clean. */
- invd
-
- /* Set up new stack. */
- movabs post_car_stack_top, %rax
- mov %rax, %rsp
#else
mov %cr0, %eax
and $(~(CR0_CD | CR0_NW)), %eax
mov %eax, %cr0
-
+#endif
/* Ensure cache is clean. */
invd
- /* Set up new stack. */
- mov post_car_stack_top, %esp
-#endif
- /*
- * Honor variable MTRR information pushed on the stack with the
- * following layout:
- *
- * Offset: Value
- * ...
- * 0x14: MTRR mask 0 63:32
- * 0x10: MTRR mask 0 31:0
- * 0x0c: MTRR base 0 63:32
- * 0x08: MTRR base 0 31:0
- * 0x04: Number of variable MTRRs to set
- * 0x00: Number of variable MTRRs to clear
- */
-
-#if CONFIG(SOC_SETS_MSRS)
-
- mov %esp, %ebp
- /* Need to align stack to 16 bytes at the call instruction. Therefore
- account for the 1 push. */
- andl $0xfffffff0, %esp
-#if ENV_X86_64
- mov %rbp, %rdi
-#else
- sub $12, %esp
- push %ebp
-#endif
-
- call soc_set_mtrrs
- /* Ignore fixing up %esp since we're setting it a new value. */
-
- /* eax: new top_of_stack with setup_stack_and_mtrrs data removed */
- movl %eax, %esp
- /* Align stack to 16 bytes at call instruction. */
- andl $0xfffffff0, %esp
- call soc_enable_mtrrs
-#else /* CONFIG_SOC_SETS_MSRS */
- /* Clear variable MTRRs. */
- pop_ebx_esi /* ebx: Number to clear, esi: Number to set */
- test %ebx, %ebx
- jz 2f
- xor %eax, %eax
- xor %edx, %edx
- mov $(MTRR_PHYS_BASE(0)), %ecx
-1:
- wrmsr
- inc %ecx
- wrmsr
- inc %ecx
- dec %ebx
- jnz 1b
-2:
-
- /* Set Variable MTRRs based on stack contents. */
- test %esi, %esi
- jz 2f
- mov $(MTRR_PHYS_BASE(0)), %ecx
-1:
- /* Write MTRR base. */
- pop_eax_edx
- wrmsr
- inc %ecx
- /* Write MTRR mask. */
- pop_eax_edx
- wrmsr
- inc %ecx
-
- dec %esi
- jnz 1b
-2:
-
- /* Enable MTRR. */
- mov $(MTRR_DEF_TYPE_MSR), %ecx
- rdmsr
- /* Make default type uncacheable. */
- and $(~(MTRR_DEF_TYPE_MASK)), %eax
- or $(MTRR_DEF_TYPE_EN), %eax
- wrmsr
-#endif /* CONFIG_SOC_SETS_MSRS */
-
movl $_estack, %esp
/* Align stack to 16 bytes at call instruction. */
andl $0xfffffff0, %esp
+ /* Call this in assembly as some platforms like to mess with the bootflow and
+ call into main directly from chipset_teardown_car. */
+ call postcar_mtrr_setup
+
/* Call into main for postcar. */
call main
/* Should never return. */
diff --git a/src/arch/x86/include/arch/romstage.h b/src/arch/x86/include/arch/romstage.h
index 28d29bfdd8..7a2a41773b 100644
--- a/src/arch/x86/include/arch/romstage.h
+++ b/src/arch/x86/include/arch/romstage.h
@@ -16,17 +16,15 @@ void mainboard_romstage_entry(void);
*/
struct postcar_frame {
- uintptr_t stack;
int skip_common_mtrr;
- struct var_mtrr_context ctx;
+ struct var_mtrr_context *mtrr;
};
/*
- * Initialize postcar_frame object allocating stack from cbmem,
- * with stack_size == 0, default 4 KiB is allocated.
+ * Initialize postcar_frame object.
* Returns 0 on success, < 0 on error.
*/
-int postcar_frame_init(struct postcar_frame *pcf, size_t stack_size);
+int postcar_frame_init(struct postcar_frame *pcf);
/*
* Add variable MTRR covering the provided range with MTRR type.
diff --git a/src/arch/x86/postcar_loader.c b/src/arch/x86/postcar_loader.c
index 0fe174bc54..d46bf3c495 100644
--- a/src/arch/x86/postcar_loader.c
+++ b/src/arch/x86/postcar_loader.c
@@ -13,65 +13,32 @@
#include <timestamp.h>
#include <security/vboot/vboot_common.h>
-static inline void stack_push(struct postcar_frame *pcf, uint32_t val)
+static size_t var_mtrr_ctx_size(void)
{
- uint32_t *ptr;
-
- pcf->stack -= sizeof(val);
- ptr = (void *)pcf->stack;
- *ptr = val;
+ int mtrr_count = get_var_mtrr_count();
+ return sizeof(struct var_mtrr_context) + mtrr_count * 2 * sizeof(msr_t);
}
-static void postcar_frame_prepare(struct postcar_frame *pcf)
+int postcar_frame_init(struct postcar_frame *pcf)
{
- var_mtrr_context_init(&pcf->ctx, pcf);
-}
-
-int postcar_frame_init(struct postcar_frame *pcf, size_t stack_size)
-{
- void *stack;
-
- /*
- * Use default postcar stack size of 4 KiB. This value should
- * not be decreased, because if mainboards use vboot, 1 KiB will
- * not be enough anymore.
- */
-
- if (stack_size == 0)
- stack_size = 4 * KiB;
+ struct var_mtrr_context *ctx;
- stack = cbmem_add(CBMEM_ID_ROMSTAGE_RAM_STACK, stack_size);
- if (stack == NULL) {
- printk(BIOS_ERR, "Couldn't add %zd byte stack in cbmem.\n",
- stack_size);
+ ctx = cbmem_add(CBMEM_ID_ROMSTAGE_RAM_STACK, var_mtrr_ctx_size());
+ if (ctx == NULL) {
+ printk(BIOS_ERR, "Couldn't add var_mtrr_ctx setup in cbmem.\n");
return -1;
}
- postcar_frame_prepare(pcf);
- pcf->stack = (uintptr_t)stack;
- pcf->stack += stack_size;
- return 0;
-}
-
-static void postcar_var_mtrr_set(const struct var_mtrr_context *ctx,
- uintptr_t addr, size_t size,
- msr_t base, msr_t mask)
-{
- struct postcar_frame *pcf = ctx->arg;
-
- printk(BIOS_DEBUG, "MTRR Range: Start=%lx End=%lx (Size %zx)\n",
- addr, addr + size - 1, size);
+ pcf->mtrr = ctx;
+ var_mtrr_context_init(pcf->mtrr);
- stack_push(pcf, mask.hi);
- stack_push(pcf, mask.lo);
- stack_push(pcf, base.hi);
- stack_push(pcf, base.lo);
+ return 0;
}
void postcar_frame_add_mtrr(struct postcar_frame *pcf,
uintptr_t addr, size_t size, int type)
{
- var_mtrr_set_with_cb(&pcf->ctx, addr, size, type, postcar_var_mtrr_set);
+ var_mtrr_set(pcf->mtrr, addr, size, type);
}
void postcar_frame_add_romcache(struct postcar_frame *pcf, int type)
@@ -94,7 +61,7 @@ static void postcar_frame_common_mtrrs(struct postcar_frame *pcf)
* cache-as-ram is torn down as well as the MTRR settings to use. */
void prepare_and_run_postcar(struct postcar_frame *pcf)
{
- if (postcar_frame_init(pcf, 0))
+ if (postcar_frame_init(pcf))
die("Unable to initialize postcar frame.\n");
fill_postcar_frame(pcf);
@@ -105,25 +72,15 @@ void prepare_and_run_postcar(struct postcar_frame *pcf)
/* We do not return here. */
}
-static void postcar_commit_mtrrs(struct postcar_frame *pcf)
-{
- /*
- * Place the number of used variable MTRRs on stack then max number
- * of variable MTRRs supported in the system.
- */
- stack_push(pcf, pcf->ctx.used_var_mtrrs);
- stack_push(pcf, pcf->ctx.max_var_mtrrs);
-}
-
-static void finalize_load(uintptr_t *stack_top_ptr, uintptr_t stack_top)
+static void finalize_load(uintptr_t *reloc_params, uintptr_t mtrr_frame_ptr)
{
- *stack_top_ptr = stack_top;
+ *reloc_params = mtrr_frame_ptr;
/*
* Signal to rest of system that another update was made to the
* postcar program prior to running it.
*/
- prog_segment_loaded((uintptr_t)stack_top_ptr, sizeof(uintptr_t),
- SEG_FINAL);
+ prog_segment_loaded((uintptr_t)reloc_params, sizeof(uintptr_t), SEG_FINAL);
+ prog_segment_loaded((uintptr_t)mtrr_frame_ptr, var_mtrr_ctx_size(), SEG_FINAL);
}
static void load_postcar_cbfs(struct prog *prog, struct postcar_frame *pcf)
@@ -144,7 +101,7 @@ static void load_postcar_cbfs(struct prog *prog, struct postcar_frame *pcf)
die_with_post_code(POST_INVALID_ROM,
"No parameters found in after CAR program.\n");
- finalize_load(rsl.params, pcf->stack);
+ finalize_load(rsl.params, (uintptr_t)pcf->mtrr);
stage_cache_add(STAGE_POSTCAR, prog);
}
@@ -177,14 +134,12 @@ void run_postcar_phase(struct postcar_frame *pcf)
struct prog prog =
PROG_INIT(PROG_POSTCAR, CONFIG_CBFS_PREFIX "/postcar");
- postcar_commit_mtrrs(pcf);
-
if (resume_from_stage_cache()) {
stage_cache_load_stage(STAGE_POSTCAR, &prog);
/* This is here to allow platforms to pass different stack
parameters between S3 resume and normal boot. On the
platforms where the values are the same it's a nop. */
- finalize_load(prog.arg, pcf->stack);
+ finalize_load(prog.arg, (uintptr_t)pcf->mtrr);
if (prog_entry(&prog) == NULL)
postcar_cache_invalid();