[coreboot-gerrit] Patch set updated for coreboot: soc/intel/apollolake: Add CQOS CAR implementation
Andrey Petrov (andrey.petrov@intel.com)
gerrit at coreboot.org
Sat Jul 30 03:26:25 CEST 2016
Andrey Petrov (andrey.petrov at intel.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/15455
-gerrit
commit 7fd0b227e219e2804030eff129cbed0bf76d3ed0
Author: Andrey Petrov <andrey.petrov at 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 at intel.com>
---
src/soc/intel/apollolake/Kconfig | 22 +++++++++
src/soc/intel/apollolake/bootblock/bootblock.c | 4 ++
src/soc/intel/apollolake/bootblock/cache_as_ram.S | 55 ++++++++++++++++++++++-
src/soc/intel/apollolake/car.c | 7 +++
src/soc/intel/apollolake/exit_car.S | 24 +++++++++-
src/soc/intel/apollolake/include/soc/cpu.h | 19 ++++++++
6 files changed, 127 insertions(+), 4 deletions(-)
diff --git a/src/soc/intel/apollolake/Kconfig b/src/soc/intel/apollolake/Kconfig
index dbf7d51..657ed56 100644
--- a/src/soc/intel/apollolake/Kconfig
+++ b/src/soc/intel/apollolake/Kconfig
@@ -224,5 +224,27 @@ config NHLT_DA7219
default n
help
Include DSP firmware settings for headset codec.
+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 31144ff..03408b6 100644
--- a/src/soc/intel/apollolake/bootblock/bootblock.c
+++ b/src/soc/intel/apollolake/bootblock/bootblock.c
@@ -171,5 +171,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 eee458d..1065f48 100644
--- a/src/soc/intel/apollolake/bootblock/cache_as_ram.S
+++ b/src/soc/intel/apollolake/bootblock/cache_as_ram.S
@@ -103,11 +103,11 @@ 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
-#error "DCACHE_RAM_SIZE is not power of 2, and we don't know how to handle this value"
+#error "DCACHE_RAM_SIZE is not a power of 2 and setup code is missing"
#endif
post_code(0x25)
@@ -124,12 +124,55 @@ 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
+#else
+ /*
+ * 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
+#endif
+
+#if IS_ENABLED(CONFIG_CAR_CQOS)
+#if (CONFIG_DCACHE_RAM_SIZE == 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 $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 */
+
+ /* Mask 0 is used for CAR */
+ mov $MTRR_L2_QOS_MASK(0), %ecx
+ rdmsr
+ mov %ebx, %eax
+ 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 %ebx, %eax
+ xor $~0, %al /* invert 8 bits */
+ wrmsr
+#endif
post_code(0x26)
/* Clear the cache memory region. This will also fill up the cache */
@@ -140,11 +183,19 @@ 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
+#else
+ /* Enable prefetchers */
+ mov $MSR_PREFETCH_CTL, %ecx
+ rdmsr
+ and $~(PREFETCH_L1_DISABLE | PREFETCH_L2_DISABLE), %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..86aadf5d 100644
--- a/src/soc/intel/apollolake/exit_car.S
+++ b/src/soc/intel/apollolake/exit_car.S
@@ -27,14 +27,33 @@ chipset_teardown_car:
*/
pop %ebx
- /* invalidate cache contents. */
- invd
/* 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 +61,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..388eca7 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
@@ -34,6 +35,24 @@ void apollolake_init_cpus(struct device *dev);
#define MSR_EVICT_CTL 0x2e0
#define MSR_EMULATE_PM_TMR 0x121
#define EMULATE_PM_TMR_EN (1 << 16)
+#define MSR_PREFETCH_CTL 0x1a4
+#define PREFETCH_L1_DISABLE (1 << 0)
+#define PREFETCH_L2_DISABLE (1 << 2)
+
+
+#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. This is calculated as:
+ * (CACHE_WAYS / CACHE_BITS_PER_MASK) * CACHE_LINE_SIZE * CACHE_SETS
+ */
+#define CACHE_QOS_SIZE_PER_BIT 128 * KiB
+#define L2_CACHE_SIZE 0x100000
#define BASE_CLOCK_MHZ 100
More information about the coreboot-gerrit
mailing list