soc/intel/common/block: Add cache as ram init and teardown code

Create sample model for common car init and teardown programming.

TEST=Booted Reef, KCRD/EVE, GLKRVP with CAR_CQOS, CAR_NEM_ENHANCED
and CAR_NEM configs till post code 0x2a.

Change-Id: Iffd0c3e3ca81a3d283d5f1da115222a222e6b157
Signed-off-by: Subrata Banik <subrata.banik@intel.com>
Reviewed-on: https://review.coreboot.org/18381
Tested-by: build bot (Jenkins)
Reviewed-by: Martin Roth <martinroth@google.com>
This commit is contained in:
Subrata Banik
2017-03-07 14:02:23 +05:30
committed by Martin Roth
parent 0637e567e1
commit 03e971cd23
9 changed files with 369 additions and 109 deletions

View File

@ -32,8 +32,8 @@
#if IS_ENABLED(CONFIG_SKIP_FSP_CAR) #if IS_ENABLED(CONFIG_SKIP_FSP_CAR)
/* SOC specific NEM */ /* chipset_teardown_car() is expected to disable cache-as-ram. */
#include <soc/car_teardown.S> call chipset_teardown_car
#else #else
.extern fih_car .extern fih_car

View File

@ -0,0 +1,32 @@
config SOC_INTEL_COMMON_BLOCK_CAR
bool
default n
help
This option allows you to select how cache-as-ram (CAR) is set up.
config INTEL_CAR_NEM
bool
default n
help
Traditionally, CAR is set up by using Non-Evict mode. This method
does not allow CAR and cache to co-exist, because cache fills are
blocked in NEM.
config INTEL_CAR_CQOS
bool
default n
help
Cache Quality of Service allows more fine-grained control of cache
usage. As result, it is possible to set up a portion of L2 cache for
CAR and use the remainder for actual caching.
config INTEL_CAR_NEM_ENHANCED
bool
default n
help
A current limitation of NEM (Non-Evict mode) is that code and data sizes
are derived from the requirement to not write out any modified cache line.
With NEM, if there is no physical memory behind the cached area,
the modified data will be lost and NEM results will be inconsistent.
ENHANCED NEM guarantees that modified data is always
kept in cache while clean data is replaced.

View File

@ -0,0 +1,3 @@
bootblock-$(CONFIG_SOC_INTEL_COMMON_BLOCK_CAR) += car/cache_as_ram.S
postcar-$(CONFIG_SOC_INTEL_COMMON_BLOCK_CAR) += car/exit_car.S
romstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_CAR) += car/exit_car.S

View File

@ -14,17 +14,13 @@
* *
*/ */
#include <commonlib/helpers.h>
#include <cpu/x86/cache.h> #include <cpu/x86/cache.h>
#include <cpu/x86/cr.h> #include <cpu/x86/cr.h>
#include <cpu/x86/mtrr.h> #include <cpu/x86/mtrr.h>
#include <cpu/x86/post_code.h> #include <cpu/x86/post_code.h>
#include <rules.h> #include <rules.h>
#include <intelblocks/msr.h>
#define IA32_PQR_ASSOC 0x0c8f
#define IA32_L3_MASK_1 0x0c91
#define IA32_L3_MASK_2 0x0c92
#define CACHE_INIT_VALUE 0
#define MSR_EVICT_CTL 0x2e0
.global bootblock_pre_c_entry .global bootblock_pre_c_entry
bootblock_pre_c_entry: bootblock_pre_c_entry:
@ -42,7 +38,7 @@ check_for_clean_reset:
and $(MTRR_DEF_TYPE_EN | MTRR_DEF_TYPE_FIX_EN), %eax and $(MTRR_DEF_TYPE_EN | MTRR_DEF_TYPE_FIX_EN), %eax
cmp $0, %eax cmp $0, %eax
jz no_reset jz no_reset
/* perform soft reset */ /* perform warm reset */
movw $0xcf9, %dx movw $0xcf9, %dx
movb $0x06, %al movb $0x06, %al
outb %al, %dx outb %al, %dx
@ -54,6 +50,7 @@ no_reset:
mov $fixed_mtrr_list_size, %ebx mov $fixed_mtrr_list_size, %ebx
xor %eax, %eax xor %eax, %eax
xor %edx, %edx xor %edx, %edx
clear_fixed_mtrr: clear_fixed_mtrr:
add $-2, %ebx add $-2, %ebx
movzwl fixed_mtrr_list(%ebx), %ecx movzwl fixed_mtrr_list(%ebx), %ecx
@ -107,6 +104,7 @@ clear_var_mtrr:
post_code(0x24) post_code(0x24)
#if ((CONFIG_DCACHE_RAM_SIZE & (CONFIG_DCACHE_RAM_SIZE - 1)) == 0)
/* Configure CAR region as write-back (WB) */ /* Configure CAR region as write-back (WB) */
mov $MTRR_PHYS_BASE(0), %ecx mov $MTRR_PHYS_BASE(0), %ecx
mov $CONFIG_DCACHE_RAM_BASE, %eax mov $CONFIG_DCACHE_RAM_BASE, %eax
@ -120,8 +118,40 @@ clear_var_mtrr:
dec %eax dec %eax
not %eax not %eax
or $MTRR_PHYS_MASK_VALID, %eax or $MTRR_PHYS_MASK_VALID, %eax
movl %esi, %edx /* edx <- MTRR_PHYS_MASK_HIGH */
wrmsr
#elif (CONFIG_DCACHE_RAM_SIZE == 768 * KiB) /* 768 KiB */
/* Configure CAR region as write-back (WB) */
mov $MTRR_PHYS_BASE(0), %ecx
mov $CONFIG_DCACHE_RAM_BASE, %eax
or $MTRR_TYPE_WRBACK, %eax
xor %edx,%edx
wrmsr wrmsr
mov $MTRR_PHYS_MASK(0), %ecx
mov $(512 * KiB), %eax /* size mask */
dec %eax
not %eax
or $MTRR_PHYS_MASK_VALID, %eax
movl %esi, %edx /* edx <- MTRR_PHYS_MASK_HIGH */
wrmsr
mov $MTRR_PHYS_BASE(1), %ecx
mov $(CONFIG_DCACHE_RAM_BASE + 512 * KiB), %eax
or $MTRR_TYPE_WRBACK, %eax
xor %edx,%edx
wrmsr
mov $MTRR_PHYS_MASK(1), %ecx
mov $(256 * KiB), %eax /* size mask */
dec %eax
not %eax
or $MTRR_PHYS_MASK_VALID, %eax
movl %esi, %edx /* edx <- MTRR_PHYS_MASK_HIGH */
wrmsr
#else
#error "DCACHE_RAM_SIZE is not a power of 2 and setup code is missing"
#endif
post_code(0x25) post_code(0x25)
/* Enable variable MTRRs */ /* Enable variable MTRRs */
@ -136,6 +166,168 @@ clear_var_mtrr:
invd invd
mov %eax, %cr0 mov %eax, %cr0
#if IS_ENABLED(CONFIG_INTEL_CAR_NEM)
jmp car_nem
#elif IS_ENABLED(CONFIG_INTEL_CAR_CQOS)
jmp car_cqos
#elif IS_ENABLED(CONFIG_INTEL_CAR_NEM_ENHANCED)
jmp car_nem_enhanced
#else
jmp .halt_forever /* In case nothing has selected */
#endif
.global car_init_done
car_init_done:
post_code(0x29)
/* Setup bootblock stack */
mov $_car_stack_end, %esp
/*push TSC value to stack*/
movd %mm2, %eax
pushl %eax /* tsc[63:32] */
movd %mm1, %eax
pushl %eax /* tsc[31:0] */
before_carstage:
post_code(0x2A)
call bootblock_c_entry
/* Never reached */
.halt_forever:
post_code(POST_DEAD_CODE)
hlt
jmp .halt_forever
fixed_mtrr_list:
.word MTRR_FIX_64K_00000
.word MTRR_FIX_16K_80000
.word MTRR_FIX_16K_A0000
.word MTRR_FIX_4K_C0000
.word MTRR_FIX_4K_C8000
.word MTRR_FIX_4K_D0000
.word MTRR_FIX_4K_D8000
.word MTRR_FIX_4K_E0000
.word MTRR_FIX_4K_E8000
.word MTRR_FIX_4K_F0000
.word MTRR_FIX_4K_F8000
fixed_mtrr_list_size = . - fixed_mtrr_list
#if IS_ENABLED(CONFIG_INTEL_CAR_NEM)
.global car_nem
car_nem:
/* Disable cache eviction (setup stage) */
mov $MSR_EVICT_CTL, %ecx
rdmsr
or $0x1, %eax
wrmsr
post_code(0x26)
/* Clear the cache memory region. This will also fill up the cache */
movl $CONFIG_DCACHE_RAM_BASE, %edi
movl $CONFIG_DCACHE_RAM_SIZE, %ecx
shr $0x02, %ecx
xor %eax, %eax
cld
rep stosl
post_code(0x27)
/* Disable cache eviction (run stage) */
mov $MSR_EVICT_CTL, %ecx
rdmsr
or $0x2, %eax
wrmsr
post_code(0x28)
jmp car_init_done
#elif IS_ENABLED(CONFIG_INTEL_CAR_CQOS)
.global car_cqos
car_cqos:
/*
* Disable both L1 and L2 prefetcher. For yet-to-understood reason,
* prefetchers slow down filling cache with rep stos in CQOS mode.
*/
mov $MSR_PREFETCH_CTL, %ecx
rdmsr
or $(PREFETCH_L1_DISABLE | PREFETCH_L2_DISABLE), %eax
wrmsr
#if (CONFIG_DCACHE_RAM_SIZE == CONFIG_L2_CACHE_SIZE)
/*
* If CAR size is set to full L2 size, mask is calculated as all-zeros.
* This is not supported by the CPU/uCode.
*/
#error "CQOS CAR may not use whole L2 cache area"
#endif
/* Calculate how many bits to be used for CAR */
xor %edx, %edx
mov $CONFIG_DCACHE_RAM_SIZE, %eax /* dividend */
mov $CONFIG_CACHE_QOS_SIZE_PER_BIT, %ecx /* divisor */
div %ecx /* result is in eax */
mov %eax, %ecx /* save to ecx */
mov $1, %ebx
shl %cl, %ebx
sub $1, %ebx /* resulting mask is is in ebx */
/* Set this mask for initial cache fill */
mov $MSR_L2_QOS_MASK(0), %ecx
rdmsr
mov %bl, %al
wrmsr
/* Set CLOS selector to 0 */
mov $MSR_IA32_PQR_ASSOC, %ecx
rdmsr
and $~IA32_PQR_ASSOC_MASK, %edx /* select mask 0 */
wrmsr
/* We will need to block CAR region from evicts */
mov $MSR_L2_QOS_MASK(1), %ecx
rdmsr
/* Invert bits that are to be used for cache */
mov %bl, %al
xor $~0, %al /* invert 8 bits */
wrmsr
post_code(0x26)
/* Clear the cache memory region. This will also fill up the cache */
movl $CONFIG_DCACHE_RAM_BASE, %edi
movl $CONFIG_DCACHE_RAM_SIZE, %ecx
shr $0x02, %ecx
xor %eax, %eax
cld
rep stosl
post_code(0x27)
/* Cache is populated. Use mask 1 that will block evicts */
mov $MSR_IA32_PQR_ASSOC, %ecx
rdmsr
and $~IA32_PQR_ASSOC_MASK, %edx /* clear index bits first */
or $1, %edx /* select mask 1 */
wrmsr
/* Enable prefetchers */
mov $MSR_PREFETCH_CTL, %ecx
rdmsr
and $~(PREFETCH_L1_DISABLE | PREFETCH_L2_DISABLE), %eax
wrmsr
post_code(0x28)
jmp car_init_done
#elif IS_ENABLED(CONFIG_INTEL_CAR_NEM_ENHANCED)
.global car_nem_enhanced
car_nem_enhanced:
/* Disable cache eviction (setup stage) */ /* Disable cache eviction (setup stage) */
mov $MSR_EVICT_CTL, %ecx mov $MSR_EVICT_CTL, %ecx
rdmsr rdmsr
@ -188,7 +380,7 @@ find_llc_subleaf:
*/ */
shl %cl, %eax shl %cl, %eax
subl $0x02, %eax subl $0x02, %eax
movl $IA32_L3_MASK_1, %ecx movl $MSR_IA32_L3_MASK_1, %ecx
xorl %edx, %edx xorl %edx, %edx
wrmsr wrmsr
/* /*
@ -197,12 +389,12 @@ find_llc_subleaf:
* For SKL SOC, data size remains 256K consistently. * For SKL SOC, data size remains 256K consistently.
* Hence, creating 1-way associative cache for Data * Hence, creating 1-way associative cache for Data
*/ */
mov $IA32_L3_MASK_2, %ecx mov $MSR_IA32_L3_MASK_2, %ecx
mov $0x01, %eax mov $0x01, %eax
xorl %edx, %edx xorl %edx, %edx
wrmsr wrmsr
/* /*
* Set IA32_PQR_ASSOC = 0x02 * Set MSR_IA32_PQR_ASSOC = 0x02
* *
* Possible values: * Possible values:
* 0: Default value, no way mask should be applied * 0: Default value, no way mask should be applied
@ -210,7 +402,7 @@ find_llc_subleaf:
* 2: Apply way mask 2 to LLC * 2: Apply way mask 2 to LLC
* 3: Shouldn't be use in NEM Mode * 3: Shouldn't be use in NEM Mode
*/ */
movl $IA32_PQR_ASSOC, %ecx movl $MSR_IA32_PQR_ASSOC, %ecx
movl $0x02, %eax movl $0x02, %eax
xorl %edx, %edx xorl %edx, %edx
wrmsr wrmsr
@ -218,15 +410,15 @@ find_llc_subleaf:
movl $CONFIG_DCACHE_RAM_BASE, %edi movl $CONFIG_DCACHE_RAM_BASE, %edi
movl $CONFIG_DCACHE_RAM_SIZE, %ecx movl $CONFIG_DCACHE_RAM_SIZE, %ecx
shr $0x02, %ecx shr $0x02, %ecx
movl $CACHE_INIT_VALUE, %eax xor %eax, %eax
cld cld
rep stosl rep stosl
/* /*
* Set IA32_PQR_ASSOC = 0x01 * Set MSR_IA32_PQR_ASSOC = 0x01
* At this stage we apply LLC_WAY_MASK_1 to the cache. * At this stage we apply LLC_WAY_MASK_1 to the cache.
* i.e. way 0 is protected from eviction. * i.e. way 0 is protected from eviction.
*/ */
movl $IA32_PQR_ASSOC, %ecx movl $MSR_IA32_PQR_ASSOC, %ecx
movl $0x01, %eax movl $0x01, %eax
xorl %edx, %edx xorl %edx, %edx
wrmsr wrmsr
@ -242,42 +434,7 @@ find_llc_subleaf:
orl $0x02, %eax orl $0x02, %eax
wrmsr wrmsr
car_init_done:
post_code(0x28) post_code(0x28)
/* Setup bootblock stack */ jmp car_init_done
mov $_car_stack_end, %esp #endif
post_code(0x29)
/*push TSC value to stack*/
movd %mm2, %eax
pushl %eax /* tsc[63:32] */
movd %mm1, %eax
pushl %eax /* tsc[31:0] */
before_carstage:
post_code(0x2A)
call bootblock_c_entry
/* Never reached */
.halt_forever:
post_code(POST_DEAD_CODE)
hlt
jmp .halt_forever
fixed_mtrr_list:
.word MTRR_FIX_64K_00000
.word MTRR_FIX_16K_80000
.word MTRR_FIX_16K_A0000
.word MTRR_FIX_4K_C0000
.word MTRR_FIX_4K_C8000
.word MTRR_FIX_4K_D0000
.word MTRR_FIX_4K_D8000
.word MTRR_FIX_4K_E0000
.word MTRR_FIX_4K_E8000
.word MTRR_FIX_4K_F0000
.word MTRR_FIX_4K_F8000
fixed_mtrr_list_size = . - fixed_mtrr_list

View File

@ -0,0 +1,96 @@
/*
* This file is part of the coreboot project.
*
* Copyright 2017 Intel Corp.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; version 2 of
* the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <cpu/x86/mtrr.h>
#include <cpu/x86/cr.h>
#include <intelblocks/msr.h>
.text
.global chipset_teardown_car
chipset_teardown_car:
/*
* Retrieve return address from stack as it will get trashed below if
* execution is utilizing the cache-as-ram stack.
*/
pop %ebx
/* Disable MTRRs. */
mov $(MTRR_DEF_TYPE_MSR), %ecx
rdmsr
and $(~(MTRR_DEF_TYPE_EN | MTRR_DEF_TYPE_FIX_EN)), %eax
wrmsr
#if IS_ENABLED(CONFIG_INTEL_CAR_NEM)
.global car_nem_teardown
car_nem_teardown:
/* invalidate cache contents. */
invd
/* Knock down bit 1 then bit 0 of NEM control not combining steps. */
mov $(MSR_EVICT_CTL), %ecx
rdmsr
and $(~(1 << 1)), %eax
wrmsr
and $(~(1 << 0)), %eax
wrmsr
#elif IS_ENABLED(CONFIG_INTEL_CAR_CQOS)
.global car_cqos_teardown
car_cqos_teardown:
/* Go back to all-evicting mode, set both masks to all-1s */
mov $MSR_L2_QOS_MASK(0), %ecx
rdmsr
mov $~0, %al
wrmsr
mov $MSR_L2_QOS_MASK(1), %ecx
rdmsr
mov $~0, %al
wrmsr
/* Reset CLOS selector to 0 */
mov $MSR_IA32_PQR_ASSOC, %ecx
rdmsr
and $~IA32_PQR_ASSOC_MASK, %edx
wrmsr
#elif IS_ENABLED(CONFIG_INTEL_CAR_NEM_ENHANCED)
.global car_nem_enhanced_teardown
car_nem_enhanced_teardown:
/* invalidate cache contents. */
invd
/* Knock down bit 1 then bit 0 of NEM control not combining steps. */
mov $(MSR_EVICT_CTL), %ecx
rdmsr
and $(~(1 << 1)), %eax
wrmsr
and $(~(1 << 0)), %eax
wrmsr
/* Reset CLOS selector to 0 */
mov $MSR_IA32_PQR_ASSOC, %ecx
rdmsr
and $~IA32_PQR_ASSOC_MASK, %edx
wrmsr
#endif
/* Return to caller. */
jmp *%ebx

View File

@ -255,6 +255,32 @@ config NHLT_MAX98927
help help
Include DSP firmware settings for max98927 amplifier. Include DSP firmware settings for max98927 amplifier.
choice
prompt "Cache-as-ram implementation"
default CAR_NEM_ENHANCED
help
This option allows you to select how cache-as-ram (CAR) is set up.
config CAR_NEM_ENHANCED
bool "Enhanced Non-evict mode"
select SOC_INTEL_COMMON_BLOCK_CAR
select INTEL_CAR_NEM_ENHANCED
help
A current limitation of NEM (Non-Evict mode) is that code and data sizes
are derived from the requirement to not write out any modified cache line.
With NEM, if there is no physical memory behind the cached area,
the modified data will be lost and NEM results will be inconsistent.
ENHANCED NEM guarantees that modified data is always
kept in cache while clean data is replaced.
config USE_SKYLAKE_FSP_CAR
bool "Use FSP CAR"
select FSP_CAR
help
Use FSP APIs to initialize & tear Down the Cache-As-Ram.
endchoice
config SKIP_FSP_CAR config SKIP_FSP_CAR
bool "Skip cache as RAM setup in FSP" bool "Skip cache as RAM setup in FSP"
default y default y

View File

@ -10,7 +10,6 @@ subdirs-y += ../../../cpu/x86/smm
subdirs-y += ../../../cpu/x86/tsc subdirs-y += ../../../cpu/x86/tsc
bootblock-y += bootblock/bootblock.c bootblock-y += bootblock/bootblock.c
bootblock-y += bootblock/cache_as_ram.S
bootblock-y += bootblock/cpu.c bootblock-y += bootblock/cpu.c
bootblock-y += bootblock/i2c.c bootblock-y += bootblock/i2c.c
bootblock-y += bootblock/pch.c bootblock-y += bootblock/pch.c

View File

@ -1,54 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013-2014 Sage Electronic Engineering, LLC.
* Copyright (C) 2016 Intel Corp.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
.equ IA32_PQR_ASSOC, 0x0c8f
/* Disable MTRR by clearing the IA32_MTRR_DEF_TYPE MSR E flag. */
movl $MTRR_DEF_TYPE_MSR, %ecx
rdmsr
andl $(~MTRR_DEF_TYPE_EN), %eax
wrmsr
/* Invalidate Cache */
invd
/*
* Disable No-Eviction Mode Run State by clearing
* NO_EVICT_MODE MSR 2E0h bit [1] = 0
*/
movl $0x000002E0, %ecx
rdmsr
andl $~(0x2), %eax
wrmsr
/*
* Disable No-Eviction Mode Setup State by clearing
* NO_EVICT_MODE MSR 2E0h bit [0] = 0
*/
rdmsr
andl $~(0x1), %eax
wrmsr
/*
* Set IA32_PQR_ASSOC = 0x00
* This step guarantees that no protected way remain in LLC cache,
* all the ways are open for the evictions.
*/
movl $IA32_PQR_ASSOC, %ecx
movl $0x00, %eax
xorl %edx, %edx
wrmsr

View File

@ -37,7 +37,8 @@ car_stage_entry:
/* Switch to the stack in RAM */ /* Switch to the stack in RAM */
movl %eax, %esp movl %eax, %esp
#include <soc/car_teardown.S> /* chipset_teardown_car() is expected to disable cache-as-ram. */
call chipset_teardown_car
/* Display the MTRRs */ /* Display the MTRRs */
call soc_display_mtrrs call soc_display_mtrrs