diff options
Diffstat (limited to 'src/arch')
-rw-r--r-- | src/arch/x86/exit_car.S | 126 | ||||
-rw-r--r-- | src/arch/x86/include/arch/romstage.h | 8 | ||||
-rw-r--r-- | src/arch/x86/postcar_loader.c | 83 |
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(); |