Andrey Petrov (andrey.petrov@intel.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/15455
-gerrit
commit 2494d599bcb3b5a26f56badfd3b6da3336c3b809 Author: Andrey Petrov andrey.petrov@intel.com Date: Mon Jun 27 13:39:34 2016 -0700
soc/intel/apollolake: Add CQOS CAR implementation
Add new Cache Quality of Service option that allows to configure cache non-evict mode by manipulating CQOS settings. Also, CQOS allows using cache non-evict mode simultaneously with regular evicting caching.
BUG=chrome-os-partner:51959
Change-Id: Ic7f9899918f94a5788b02a4fbd2f5d5ba9aaf91d Signed-off-by: Andrey Petrov andrey.petrov@intel.com --- src/soc/intel/apollolake/Kconfig | 23 ++++++++++++++++++ src/soc/intel/apollolake/bootblock/bootblock.c | 4 ++++ src/soc/intel/apollolake/bootblock/cache_as_ram.S | 26 +++++++++++++++++++- src/soc/intel/apollolake/car.c | 7 ++++++ src/soc/intel/apollolake/exit_car.S | 29 +++++++++++++++++++++-- src/soc/intel/apollolake/include/soc/cpu.h | 12 ++++++++++ 6 files changed, 98 insertions(+), 3 deletions(-)
diff --git a/src/soc/intel/apollolake/Kconfig b/src/soc/intel/apollolake/Kconfig index 43249f1..d828f23 100644 --- a/src/soc/intel/apollolake/Kconfig +++ b/src/soc/intel/apollolake/Kconfig @@ -182,4 +182,27 @@ config IFWI_FILE_NAME help Name of file to store in the IFWI region.
+choice + prompt "Cache-as-ram implementation" + default CAR_CQOS + help + This option allows you to select how cache-as-ram (CAR) is set up. + +config CAR_NEM + bool "Non-evict mode" + 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 + block in NEM mode. + + +config CAR_CQOS + bool "Cache Quality of Service" + help + Cache Quality of Service allows more fine-grained control of cache + usage. As result, it is possible to set up portion of L2 cache for + CAR and use remainded for actual caching. + +endchoice + endif diff --git a/src/soc/intel/apollolake/bootblock/bootblock.c b/src/soc/intel/apollolake/bootblock/bootblock.c index 8c1ff91..00c280a 100644 --- a/src/soc/intel/apollolake/bootblock/bootblock.c +++ b/src/soc/intel/apollolake/bootblock/bootblock.c @@ -168,5 +168,9 @@ void bootblock_soc_early_init(void)
enable_spibar();
+#if IS_ENABLED(CONFIG_CAR_CQOS) + cache_qos_select_mask(1); +#endif + cache_bios_region(); } diff --git a/src/soc/intel/apollolake/bootblock/cache_as_ram.S b/src/soc/intel/apollolake/bootblock/cache_as_ram.S index 8436d51..6f670c6 100644 --- a/src/soc/intel/apollolake/bootblock/cache_as_ram.S +++ b/src/soc/intel/apollolake/bootblock/cache_as_ram.S @@ -103,7 +103,7 @@ clear_var_mtrr: wrmsr
mov $MTRR_PHYS_MASK(1), %ecx - mov $~(0x256 * KiB - 1), %eax /* size mask */ + mov $~(256 * KiB - 1), %eax /* size mask */ or $MTRR_PHYS_MASK_VALID, %eax wrmsr #else @@ -124,12 +124,34 @@ clear_var_mtrr: invd mov %eax, %cr0
+#if IS_ENABLED(CONFIG_CAR_NEM) /* Disable cache eviction (setup stage) */ mov $MSR_EVICT_CTL, %ecx rdmsr or $0x1, %eax wrmsr +#endif + +#if IS_ENABLED(CONFIG_CAR_CQOS) +/* Mask can't be set to all zeros */ +#if ((((1 << (CONFIG_DCACHE_RAM_SIZE / CACHE_QOS_SIZE_PER_BIT)) - 1) & 0xff) == 0xff) +#error "calculated class of service mask is all-zeros, which is unsupported by the CPU" +#endif + /* Mask 0 is used for CAR */ + mov $MTRR_L2_QOS_MASK(0), %ecx + rdmsr + /* Calculate how many bits to be used for CAR */ + mov $(1 << ((CONFIG_DCACHE_RAM_SIZE / CACHE_QOS_SIZE_PER_BIT)) - 1), %al + wrmsr
+ /* Mask 1 is used for evicatable cache */ + mov $MTRR_L2_QOS_MASK(1), %ecx + rdmsr + /* Invert bits that are to be used for cache */ + mov $(1 << ((CONFIG_DCACHE_RAM_SIZE / CACHE_QOS_SIZE_PER_BIT)) - 1), %al + xor $~0, %al + wrmsr +#endif post_code(0x26)
/* Clear the cache memory region. This will also fill up the cache */ @@ -140,11 +162,13 @@ clear_var_mtrr:
post_code(0x27)
+#if IS_ENABLED(CONFIG_CAR_NEM) /* Disable cache eviction (run stage) */ mov $MSR_EVICT_CTL, %ecx rdmsr or $0x2, %eax wrmsr +#endif
post_code(0x28)
diff --git a/src/soc/intel/apollolake/car.c b/src/soc/intel/apollolake/car.c index 68bcb31..bb96419 100644 --- a/src/soc/intel/apollolake/car.c +++ b/src/soc/intel/apollolake/car.c @@ -56,3 +56,10 @@ void platform_segment_loaded(uintptr_t start, size_t size, int flags)
flush_l1d_to_l2(); } + +void cache_qos_select_mask(uint8_t mask) +{ + msr_t msr = rdmsr(MTRR_IA32_PQR_ASSOC); + msr.hi |= mask; + wrmsr(MTRR_IA32_PQR_ASSOC, msr); +} diff --git a/src/soc/intel/apollolake/exit_car.S b/src/soc/intel/apollolake/exit_car.S index 339242b..e5706cf 100644 --- a/src/soc/intel/apollolake/exit_car.S +++ b/src/soc/intel/apollolake/exit_car.S @@ -27,14 +27,38 @@ chipset_teardown_car: */ pop %ebx
- /* invalidate cache contents. */ - invd + /* + * Flush all cache lines into the DRAM. Since we are running in the + * very region, disable MTRR first. + */ + /* 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_CAR_CQOS) + mov $MTRR_L2_QOS_MASK(0), %ecx + rdmsr + mov $~0, %al + wrmsr + + mov $MTRR_L2_QOS_MASK(1), %ecx + rdmsr + mov $~0, %al + wrmsr + + /* reset CLOS selector */ + mov $MTRR_IA32_PQR_ASSOC, %ecx + rdmsr + and $~(1 << 0 | 1 << 1), %edx + wrmsr +#endif + /* invalidate cache contents. */ + invd + +#if IS_ENABLED(CONFIG_CAR_NEM) /* Knock down bit 1 then bit 0 of NEM control not combining steps. */ mov $(MSR_EVICT_CTL), %ecx rdmsr @@ -42,6 +66,7 @@ chipset_teardown_car: wrmsr and $(~(1 << 0)), %eax wrmsr +#endif
/* Return to caller. */ jmp *%ebx diff --git a/src/soc/intel/apollolake/include/soc/cpu.h b/src/soc/intel/apollolake/include/soc/cpu.h index 78fc0b0..13a47cd 100644 --- a/src/soc/intel/apollolake/include/soc/cpu.h +++ b/src/soc/intel/apollolake/include/soc/cpu.h @@ -23,6 +23,7 @@ #include <device/device.h>
void apollolake_init_cpus(struct device *dev); +void cache_qos_select_mask(uint8_t mask); #endif
#define CPUID_APOLLOLAKE_A0 0x506c8 @@ -35,6 +36,17 @@ void apollolake_init_cpus(struct device *dev); #define MSR_EMULATE_PM_TMR 0x121 #define EMULATE_PM_TMR_EN (1 << 16)
+#define MTRR_L2_QOS_MASK(reg) (0xd10 + reg) +#define MTRR_IA32_PQR_ASSOC 0xc8f +/* 16 way cache, 8 bits per QOS, 64 byte cache line, 1024 sets */ +#define CACHE_WAYS 16 +#define CACHE_BITS_PER_MASK 8 +#define CACHE_LINE_SIZE 64 +#define CACHE_SETS 1024 +/* Each bit in QOS mask controls this many bytes */ +#define CACHE_QOS_SIZE_PER_BIT ((CACHE_WAYS / CACHE_BITS_PER_MASK) * \ + CACHE_LINE_SIZE * CACHE_SETS) + #define BASE_CLOCK_MHZ 100
/* Common Timer Copy (CTC) frequency - 19.2MHz. */