diff options
-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 | ||||
-rw-r--r-- | src/cpu/x86/mtrr/Makefile.inc | 2 | ||||
-rw-r--r-- | src/cpu/x86/mtrr/earlymtrr.c | 39 | ||||
-rw-r--r-- | src/drivers/amd/agesa/mtrr_fixme.c | 2 | ||||
-rw-r--r-- | src/drivers/amd/agesa/romstage.c | 2 | ||||
-rw-r--r-- | src/include/cpu/x86/mtrr.h | 42 | ||||
-rw-r--r-- | src/soc/amd/common/block/cpu/noncar/early_cache.c | 23 | ||||
-rw-r--r-- | src/soc/amd/stoneyridge/romstage.c | 2 | ||||
-rw-r--r-- | src/soc/intel/quark/romstage/Makefile.inc | 3 | ||||
-rw-r--r-- | src/soc/intel/quark/romstage/mtrr.c | 81 |
12 files changed, 81 insertions, 332 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(); diff --git a/src/cpu/x86/mtrr/Makefile.inc b/src/cpu/x86/mtrr/Makefile.inc index ac6502608b..87e61b21e4 100644 --- a/src/cpu/x86/mtrr/Makefile.inc +++ b/src/cpu/x86/mtrr/Makefile.inc @@ -1,6 +1,7 @@ ramstage-y += mtrr.c ramstage-y += mtrrlib.c +postcar-y += mtrrlib.c romstage-y += mtrrlib.c bootblock-y += mtrrlib.c verstage_x86-y += mtrrlib.c @@ -8,6 +9,7 @@ verstage_x86-y += mtrrlib.c romstage-y += earlymtrr.c bootblock-y += earlymtrr.c verstage_x86-y += earlymtrr.c +postcar-y += earlymtrr.c bootblock-y += debug.c romstage-y += debug.c diff --git a/src/cpu/x86/mtrr/earlymtrr.c b/src/cpu/x86/mtrr/earlymtrr.c index a2d6e11d5f..8ea1216384 100644 --- a/src/cpu/x86/mtrr/earlymtrr.c +++ b/src/cpu/x86/mtrr/earlymtrr.c @@ -5,20 +5,17 @@ #include <cpu/x86/msr.h> #include <console/console.h> #include <commonlib/bsd/helpers.h> +#include <stdint.h> -void var_mtrr_context_init(struct var_mtrr_context *ctx, void *arg) +void var_mtrr_context_init(struct var_mtrr_context *ctx) { - ctx->upper_mask = (1U << (cpu_phys_address_size() - 32)) - 1; ctx->max_var_mtrrs = get_var_mtrr_count(); ctx->used_var_mtrrs = 0; - ctx->arg = arg; } -int var_mtrr_set_with_cb(struct var_mtrr_context *ctx, uintptr_t addr, size_t size, - int type, void (*callback)(const struct var_mtrr_context *ctx, - uintptr_t base_addr, size_t size, - msr_t base, msr_t mask)) +int var_mtrr_set(struct var_mtrr_context *ctx, uintptr_t addr, size_t size, int type) { + const uint32_t upper_mask = (1U << (cpu_phys_address_size() - 32)) - 1; /* Utilize additional MTRRs if the specified size is greater than the base address alignment. */ while (size != 0) { @@ -47,9 +44,10 @@ int var_mtrr_set_with_cb(struct var_mtrr_context *ctx, uintptr_t addr, size_t si base.hi = (uint64_t)addr >> 32; base.lo = addr | type; - mask.hi = ctx->upper_mask; + mask.hi = upper_mask; mask.lo = ~(mtrr_size - 1) | MTRR_PHYS_MASK_VALID; - callback(ctx, addr, mtrr_size, base, mask); + ctx->mtrr[ctx->used_var_mtrrs].base = base; + ctx->mtrr[ctx->used_var_mtrrs].mask = mask; ctx->used_var_mtrrs++; size -= mtrr_size; @@ -59,16 +57,25 @@ int var_mtrr_set_with_cb(struct var_mtrr_context *ctx, uintptr_t addr, size_t si return 0; } -static void set_mtrr(const struct var_mtrr_context *ctx, uintptr_t base_addr, size_t size, - msr_t base, msr_t mask) +/* Romstage sets up a MTRR context in cbmem and sets up this pointer in postcar stage. */ +__attribute__((used, __section__(".module_parameters"))) const volatile uintptr_t post_car_mtrrs; + +void commit_mtrr_setup(const struct var_mtrr_context *ctx) { - int i = var_mtrr_context_current_mtrr(ctx); + clear_all_var_mtrr(); - wrmsr(MTRR_PHYS_BASE(i), base); - wrmsr(MTRR_PHYS_MASK(i), mask); + for (int i = 0; i < ctx->used_var_mtrrs; i++) { + wrmsr(MTRR_PHYS_BASE(i), ctx->mtrr[i].base); + wrmsr(MTRR_PHYS_MASK(i), ctx->mtrr[i].mask); + } + /* Enable MTRR */ + msr_t mtrr_def_type = rdmsr(MTRR_DEF_TYPE_MSR); + mtrr_def_type.lo &= MTRR_DEF_TYPE_MASK; + mtrr_def_type.lo |= MTRR_DEF_TYPE_EN; + wrmsr(MTRR_DEF_TYPE_MSR, mtrr_def_type); } -int var_mtrr_set(struct var_mtrr_context *ctx, uintptr_t addr, size_t size, int type) +void postcar_mtrr_setup(void) { - return var_mtrr_set_with_cb(ctx, addr, size, type, set_mtrr); + commit_mtrr_setup((const struct var_mtrr_context *)post_car_mtrrs); } diff --git a/src/drivers/amd/agesa/mtrr_fixme.c b/src/drivers/amd/agesa/mtrr_fixme.c index 1313b5d6ec..b8b8ef05e0 100644 --- a/src/drivers/amd/agesa/mtrr_fixme.c +++ b/src/drivers/amd/agesa/mtrr_fixme.c @@ -58,7 +58,7 @@ void recover_postcar_frame(struct postcar_frame *pcf, int s3resume) /* Replicate non-UC MTRRs as left behind by AGESA. */ - for (i = 0; i < pcf->ctx.max_var_mtrrs; i++) { + for (i = 0; i < pcf->mtrr->max_var_mtrrs; i++) { mask = rdmsr(MTRR_PHYS_MASK(i)); base = rdmsr(MTRR_PHYS_BASE(i)); u32 size = ~(mask.lo & ~0xfff) + 1; diff --git a/src/drivers/amd/agesa/romstage.c b/src/drivers/amd/agesa/romstage.c index ec798eece7..648a0451b3 100644 --- a/src/drivers/amd/agesa/romstage.c +++ b/src/drivers/amd/agesa/romstage.c @@ -78,7 +78,7 @@ static void romstage_main(void) romstage_handoff_init(cb->s3resume); - postcar_frame_init(&pcf, HIGH_ROMSTAGE_STACK_SIZE); + postcar_frame_init(&pcf); recover_postcar_frame(&pcf, cb->s3resume); run_postcar_phase(&pcf); diff --git a/src/include/cpu/x86/mtrr.h b/src/include/cpu/x86/mtrr.h index 5a237845cd..5397d33948 100644 --- a/src/include/cpu/x86/mtrr.h +++ b/src/include/cpu/x86/mtrr.h @@ -114,43 +114,19 @@ void clear_all_var_mtrr(void); asmlinkage void display_mtrrs(void); -/* Variable MTRR structure to help track and set MTRRs prior to ramstage. This - and the following APIs can be used to set up more complex MTRR solutions - instead of open coding get_free_var_mtrr() and set_var_mtrr() or for determining - a future solution, such as postcar_loader. */ struct var_mtrr_context { - uint32_t upper_mask; - int max_var_mtrrs; - int used_var_mtrrs; - void *arg; /* optional callback parameter */ + uint32_t max_var_mtrrs; + uint32_t used_var_mtrrs; + struct { + msr_t base; + msr_t mask; + } mtrr[]; }; -/* Returns 0-relative MTRR from context. Use MTRR_PHYS_BASE|MASK macros for calculating - MSR address value. */ -static inline int var_mtrr_context_current_mtrr(const struct var_mtrr_context *ctx) -{ - return ctx->used_var_mtrrs; -} - -/* Initialize var_mtrr_context object. Assumes all variable MTRRs are not yet used. */ -void var_mtrr_context_init(struct var_mtrr_context *ctx, void *arg); -/* Allocate a variable mtrr base and mask, calling the provided callback for each MTRR - MSR base-mask pair needed to accommodate the address and size request. - Returns < 0 on error and 0 on success. */ -int var_mtrr_set_with_cb(struct var_mtrr_context *ctx, - uintptr_t addr, size_t size, int type, - void (*callback)(const struct var_mtrr_context *ctx, - uintptr_t base_addr, size_t size, - msr_t base, msr_t mask)); -/* Same as var_mtrr_set_with_cb() but just write the MSRs directly. */ +void var_mtrr_context_init(struct var_mtrr_context *ctx); int var_mtrr_set(struct var_mtrr_context *ctx, uintptr_t addr, size_t size, int type); - -/* - * Set the MTRRs using the data on the stack from setup_stack_and_mtrrs. - * Return a new top_of_stack value which removes the setup_stack_and_mtrrs data. - */ -asmlinkage void *soc_set_mtrrs(void *top_of_stack); -asmlinkage void soc_enable_mtrrs(void); +void commit_mtrr_setup(const struct var_mtrr_context *ctx); +void postcar_mtrr_setup(void); /* fms: find most significant bit set, stolen from Linux Kernel Source. */ static inline unsigned int fms(unsigned int x) diff --git a/src/soc/amd/common/block/cpu/noncar/early_cache.c b/src/soc/amd/common/block/cpu/noncar/early_cache.c index b9650a96a7..94c8b10272 100644 --- a/src/soc/amd/common/block/cpu/noncar/early_cache.c +++ b/src/soc/amd/common/block/cpu/noncar/early_cache.c @@ -1,11 +1,16 @@ /* SPDX-License-Identifier: GPL-2.0-only */ #include <amdblocks/cpu.h> +#include <assert.h> #include <cpu/amd/mtrr.h> #include <cpu/x86/cache.h> #include <cpu/x86/msr.h> #include <cpu/x86/mtrr.h> #include <soc/iomap.h> +#include <stdint.h> + +/* Allocate a static amount of stack for the MTRR context. */ +#define MAX_VAR_MTRR_USE 10 /* * PSP performs the memory training and setting up DRAM map prior to x86 cores being released. @@ -19,9 +24,15 @@ void early_cache_setup(void) msr_t mtrr_def_type; msr_t fixed_mtrr_ram; msr_t fixed_mtrr_mmio; - struct var_mtrr_context mtrr_ctx; + union mtrr_ctx { + struct var_mtrr_context ctx; + char buffer[sizeof(struct var_mtrr_context) + + 2 * MAX_VAR_MTRR_USE * sizeof(msr_t)]; + + } mtrr_ctx; - var_mtrr_context_init(&mtrr_ctx, NULL); + var_mtrr_context_init(&mtrr_ctx.ctx); + mtrr_ctx.ctx.max_var_mtrrs = MIN(MAX_VAR_MTRR_USE, mtrr_ctx.ctx.max_var_mtrrs); top_mem = rdmsr(TOP_MEM); /* Enable RdDram and WrDram attributes in fixed MTRRs. */ sys_cfg = rdmsr(SYSCFG_MSR); @@ -49,11 +60,11 @@ void early_cache_setup(void) wrmsr(SYSCFG_MSR, sys_cfg); - clear_all_var_mtrr(); - - var_mtrr_set(&mtrr_ctx, 0, ALIGN_DOWN(top_mem.lo, 8*MiB), MTRR_TYPE_WRBACK); + var_mtrr_set(&mtrr_ctx.ctx, 0, ALIGN_DOWN(top_mem.lo, 8*MiB), MTRR_TYPE_WRBACK); /* TODO: check if we should always mark 16 MByte below 4 GByte as WRPROT */ - var_mtrr_set(&mtrr_ctx, FLASH_BASE_ADDR, CONFIG_ROM_SIZE, MTRR_TYPE_WRPROT); + var_mtrr_set(&mtrr_ctx.ctx, FLASH_BASE_ADDR, CONFIG_ROM_SIZE, MTRR_TYPE_WRPROT); + + commit_mtrr_setup(&mtrr_ctx.ctx); /* Set up RAM caching for everything below 1MiB except for 0xa0000-0xc0000 . */ wrmsr(MTRR_FIX_64K_00000, fixed_mtrr_ram); diff --git a/src/soc/amd/stoneyridge/romstage.c b/src/soc/amd/stoneyridge/romstage.c index 8ac2eb5a04..a2037fced6 100644 --- a/src/soc/amd/stoneyridge/romstage.c +++ b/src/soc/amd/stoneyridge/romstage.c @@ -121,7 +121,7 @@ asmlinkage void car_stage_entry(void) smm_list_regions(); post_code(0x44); - if (postcar_frame_init(&pcf, 0)) + if (postcar_frame_init(&pcf)) die("Unable to initialize postcar frame.\n"); /* diff --git a/src/soc/intel/quark/romstage/Makefile.inc b/src/soc/intel/quark/romstage/Makefile.inc index 8630acb4dd..ff9b2b6743 100644 --- a/src/soc/intel/quark/romstage/Makefile.inc +++ b/src/soc/intel/quark/romstage/Makefile.inc @@ -3,10 +3,7 @@ romstage-y += car.c romstage-$(CONFIG_DISPLAY_UPD_DATA) += debug.c romstage-y += fsp_params.c -romstage-y += mtrr.c romstage-y += pcie.c romstage-y += report_platform.c romstage-y += romstage.c romstage-y += ../../../../cpu/intel/car/romstage.c - -postcar-y += mtrr.c diff --git a/src/soc/intel/quark/romstage/mtrr.c b/src/soc/intel/quark/romstage/mtrr.c deleted file mode 100644 index e72ce335d7..0000000000 --- a/src/soc/intel/quark/romstage/mtrr.c +++ /dev/null @@ -1,81 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ - -#include <cpu/x86/msr.h> -#include <cpu/x86/mtrr.h> -#include <soc/pci_devs.h> -#include <soc/reg_access.h> - -asmlinkage void *soc_set_mtrrs(void *top_of_stack) -{ - union { - uint32_t u32[2]; - uint64_t u64; - msr_t msr; - } data; - uint32_t mtrr_count; - uint32_t *mtrr_data; - uint32_t mtrr_reg; - - /* - * The stack contents are initialized in src/soc/intel/common/stack.c - * to be the following: - * - * * - * * - * * - * +36: MTRR mask 1 63:32 - * +32: MTRR mask 1 31:0 - * +28: MTRR base 1 63:32 - * +24: MTRR base 1 31:0 - * +20: MTRR mask 0 63:32 - * +16: MTRR mask 0 31:0 - * +12: MTRR base 0 63:32 - * +8: MTRR base 0 31:0 - * +4: Number of MTRRs to setup (described above) - * top_of_stack --> +0: Number of variable MTRRs to clear - * - * This routine: - * * Clears all of the variable MTRRs - * * Initializes the variable MTRRs with the data passed in - * * Returns the new top of stack after removing all of the - * data passed in. - */ - - /* Clear all of the variable MTRRs (base and mask). */ - mtrr_reg = MTRR_PHYS_BASE(0); - mtrr_data = top_of_stack; - mtrr_count = (*mtrr_data++) * 2; - data.u64 = 0; - while (mtrr_count-- > 0) - soc_msr_write(mtrr_reg++, data.msr); - - /* Setup the specified variable MTRRs */ - mtrr_reg = MTRR_PHYS_BASE(0); - mtrr_count = *mtrr_data++; - while (mtrr_count-- > 0) { - data.u32[0] = *mtrr_data++; - data.u32[1] = *mtrr_data++; - soc_msr_write(mtrr_reg++, data.msr); /* Base */ - data.u32[0] = *mtrr_data++; - data.u32[1] = *mtrr_data++; - soc_msr_write(mtrr_reg++, data.msr); /* Mask */ - } - - /* Remove setup_stack_and_mtrrs data and return the new top_of_stack */ - top_of_stack = mtrr_data; - return top_of_stack; -} - -asmlinkage void soc_enable_mtrrs(void) -{ - union { - uint32_t u32[2]; - uint64_t u64; - msr_t msr; - } data; - - /* Enable MTRR. */ - data.msr = soc_msr_read(MTRR_DEF_TYPE_MSR); - data.u32[0] |= MTRR_DEF_TYPE_EN; - soc_msr_write(MTRR_DEF_TYPE_MSR, data.msr); -} |