summaryrefslogtreecommitdiff
path: root/src/arch/x86
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/x86')
-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();