diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/drivers/intel/fsp1_1/after_raminit.S | 4 | ||||
-rw-r--r-- | src/soc/intel/common/block/cpu/Kconfig | 32 | ||||
-rw-r--r-- | src/soc/intel/common/block/cpu/Makefile.inc | 3 | ||||
-rw-r--r-- | src/soc/intel/common/block/cpu/car/cache_as_ram.S (renamed from src/soc/intel/skylake/bootblock/cache_as_ram.S) | 259 | ||||
-rw-r--r-- | src/soc/intel/common/block/cpu/car/exit_car.S | 96 | ||||
-rw-r--r-- | src/soc/intel/skylake/Kconfig | 26 | ||||
-rw-r--r-- | src/soc/intel/skylake/Makefile.inc | 1 | ||||
-rw-r--r-- | src/soc/intel/skylake/include/soc/car_teardown.S | 54 | ||||
-rw-r--r-- | src/soc/intel/skylake/romstage/car_stage_fsp20.S | 3 |
9 files changed, 369 insertions, 109 deletions
diff --git a/src/drivers/intel/fsp1_1/after_raminit.S b/src/drivers/intel/fsp1_1/after_raminit.S index 3a4116a5af..cd56ea8dc3 100644 --- a/src/drivers/intel/fsp1_1/after_raminit.S +++ b/src/drivers/intel/fsp1_1/after_raminit.S @@ -32,8 +32,8 @@ #if IS_ENABLED(CONFIG_SKIP_FSP_CAR) - /* SOC specific NEM */ - #include <soc/car_teardown.S> + /* chipset_teardown_car() is expected to disable cache-as-ram. */ + call chipset_teardown_car #else .extern fih_car diff --git a/src/soc/intel/common/block/cpu/Kconfig b/src/soc/intel/common/block/cpu/Kconfig new file mode 100644 index 0000000000..7b78c53ea7 --- /dev/null +++ b/src/soc/intel/common/block/cpu/Kconfig @@ -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. diff --git a/src/soc/intel/common/block/cpu/Makefile.inc b/src/soc/intel/common/block/cpu/Makefile.inc new file mode 100644 index 0000000000..abdff2f58b --- /dev/null +++ b/src/soc/intel/common/block/cpu/Makefile.inc @@ -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 diff --git a/src/soc/intel/skylake/bootblock/cache_as_ram.S b/src/soc/intel/common/block/cpu/car/cache_as_ram.S index 04abba65fd..79c5c77d27 100644 --- a/src/soc/intel/skylake/bootblock/cache_as_ram.S +++ b/src/soc/intel/common/block/cpu/car/cache_as_ram.S @@ -14,17 +14,13 @@ * */ +#include <commonlib/helpers.h> #include <cpu/x86/cache.h> #include <cpu/x86/cr.h> #include <cpu/x86/mtrr.h> #include <cpu/x86/post_code.h> #include <rules.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 +#include <intelblocks/msr.h> .global 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 cmp $0, %eax jz no_reset - /* perform soft reset */ + /* perform warm reset */ movw $0xcf9, %dx movb $0x06, %al outb %al, %dx @@ -54,6 +50,7 @@ no_reset: mov $fixed_mtrr_list_size, %ebx xor %eax, %eax xor %edx, %edx + clear_fixed_mtrr: add $-2, %ebx movzwl fixed_mtrr_list(%ebx), %ecx @@ -107,6 +104,7 @@ clear_var_mtrr: post_code(0x24) +#if ((CONFIG_DCACHE_RAM_SIZE & (CONFIG_DCACHE_RAM_SIZE - 1)) == 0) /* Configure CAR region as write-back (WB) */ mov $MTRR_PHYS_BASE(0), %ecx mov $CONFIG_DCACHE_RAM_BASE, %eax @@ -120,8 +118,40 @@ clear_var_mtrr: dec %eax not %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 + + 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) /* Enable variable MTRRs */ @@ -136,6 +166,168 @@ clear_var_mtrr: invd 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) */ mov $MSR_EVICT_CTL, %ecx rdmsr @@ -188,7 +380,7 @@ find_llc_subleaf: */ shl %cl, %eax subl $0x02, %eax - movl $IA32_L3_MASK_1, %ecx + movl $MSR_IA32_L3_MASK_1, %ecx xorl %edx, %edx wrmsr /* @@ -197,12 +389,12 @@ find_llc_subleaf: * For SKL SOC, data size remains 256K consistently. * Hence, creating 1-way associative cache for Data */ - mov $IA32_L3_MASK_2, %ecx + mov $MSR_IA32_L3_MASK_2, %ecx mov $0x01, %eax xorl %edx, %edx wrmsr /* - * Set IA32_PQR_ASSOC = 0x02 + * Set MSR_IA32_PQR_ASSOC = 0x02 * * Possible values: * 0: Default value, no way mask should be applied @@ -210,7 +402,7 @@ find_llc_subleaf: * 2: Apply way mask 2 to LLC * 3: Shouldn't be use in NEM Mode */ - movl $IA32_PQR_ASSOC, %ecx + movl $MSR_IA32_PQR_ASSOC, %ecx movl $0x02, %eax xorl %edx, %edx wrmsr @@ -218,15 +410,15 @@ find_llc_subleaf: movl $CONFIG_DCACHE_RAM_BASE, %edi movl $CONFIG_DCACHE_RAM_SIZE, %ecx shr $0x02, %ecx - movl $CACHE_INIT_VALUE, %eax + xor %eax, %eax cld 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. * i.e. way 0 is protected from eviction. */ - movl $IA32_PQR_ASSOC, %ecx + movl $MSR_IA32_PQR_ASSOC, %ecx movl $0x01, %eax xorl %edx, %edx wrmsr @@ -242,42 +434,7 @@ find_llc_subleaf: orl $0x02, %eax wrmsr -car_init_done: - post_code(0x28) - /* Setup bootblock stack */ - mov $_car_stack_end, %esp - - 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 + jmp car_init_done +#endif diff --git a/src/soc/intel/common/block/cpu/car/exit_car.S b/src/soc/intel/common/block/cpu/car/exit_car.S new file mode 100644 index 0000000000..15e7f17358 --- /dev/null +++ b/src/soc/intel/common/block/cpu/car/exit_car.S @@ -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 diff --git a/src/soc/intel/skylake/Kconfig b/src/soc/intel/skylake/Kconfig index a56d0444de..ebdcbe3a24 100644 --- a/src/soc/intel/skylake/Kconfig +++ b/src/soc/intel/skylake/Kconfig @@ -255,6 +255,32 @@ config NHLT_MAX98927 help 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 bool "Skip cache as RAM setup in FSP" default y diff --git a/src/soc/intel/skylake/Makefile.inc b/src/soc/intel/skylake/Makefile.inc index 1d5d89f3e5..49f818d2ff 100644 --- a/src/soc/intel/skylake/Makefile.inc +++ b/src/soc/intel/skylake/Makefile.inc @@ -10,7 +10,6 @@ subdirs-y += ../../../cpu/x86/smm subdirs-y += ../../../cpu/x86/tsc bootblock-y += bootblock/bootblock.c -bootblock-y += bootblock/cache_as_ram.S bootblock-y += bootblock/cpu.c bootblock-y += bootblock/i2c.c bootblock-y += bootblock/pch.c diff --git a/src/soc/intel/skylake/include/soc/car_teardown.S b/src/soc/intel/skylake/include/soc/car_teardown.S deleted file mode 100644 index 315b3c1deb..0000000000 --- a/src/soc/intel/skylake/include/soc/car_teardown.S +++ /dev/null @@ -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 diff --git a/src/soc/intel/skylake/romstage/car_stage_fsp20.S b/src/soc/intel/skylake/romstage/car_stage_fsp20.S index c6401fa597..5ef8bd61bf 100644 --- a/src/soc/intel/skylake/romstage/car_stage_fsp20.S +++ b/src/soc/intel/skylake/romstage/car_stage_fsp20.S @@ -37,7 +37,8 @@ car_stage_entry: /* Switch to the stack in RAM */ 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 */ call soc_display_mtrrs |