summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/soc/intel/common/block/cpu/car/cache_as_ram.S50
1 files changed, 44 insertions, 6 deletions
diff --git a/src/soc/intel/common/block/cpu/car/cache_as_ram.S b/src/soc/intel/common/block/cpu/car/cache_as_ram.S
index 3817fa5b99..db1345ac42 100644
--- a/src/soc/intel/common/block/cpu/car/cache_as_ram.S
+++ b/src/soc/intel/common/block/cpu/car/cache_as_ram.S
@@ -12,6 +12,35 @@
.section .init, "ax", @progbits
.code32
+
+/*
+ * macro: find_free_mtrr
+ * Clobbers: %eax, %ebx, %ecx, %edx.
+ * Returns:
+ * %ebx contains the number of freely available MTRR's.
+ * It should be checked against 0.
+ * %ecx holds the MTRR_BASE of the free MTRR.
+ */
+.macro find_free_mtrr
+ /* Figure out how many MTRRs we have */
+ mov $MTRR_CAP_MSR, %ecx
+ rdmsr
+ movzb %al, %ebx /* Number of variable MTRRs */
+
+ /* Find a free variable MTRR */
+ movl $MTRR_PHYS_MASK(0), %ecx
+1:
+ rdmsr
+ test $MTRR_PHYS_MASK_VALID, %eax
+ jz 2f
+ addl $2, %ecx
+ dec %ebx
+ jnz 1b
+2:
+ /* %ecx needs to hold the MTRR_BASE */
+ decl %ecx
+.endm
+
.global bootblock_pre_c_entry
bootblock_pre_c_entry:
@@ -82,15 +111,18 @@ clear_var_mtrr:
post_code(0x24)
#if ((CONFIG_DCACHE_RAM_SIZE & (CONFIG_DCACHE_RAM_SIZE - 1)) == 0)
+ find_free_mtrr
+ test %ebx, %ebx
+ jz .halt_forever
+
/* 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
/* Configure the MTRR mask for the size region */
- mov $MTRR_PHYS_MASK(0), %ecx
+ inc %ecx
mov $CONFIG_DCACHE_RAM_SIZE, %eax /* size mask */
dec %eax
not %eax
@@ -98,14 +130,17 @@ clear_var_mtrr:
movl %esi, %edx /* edx <- MTRR_PHYS_MASK_HIGH */
wrmsr
#elif (CONFIG_DCACHE_RAM_SIZE == 768 * KiB) /* 768 KiB */
+ find_free_mtrr
+ test %ebx, %ebx
+ jz .halt_forever
+
/* 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
+ incl %ecx
mov $(512 * KiB), %eax /* size mask */
dec %eax
not %eax
@@ -113,13 +148,16 @@ clear_var_mtrr:
movl %esi, %edx /* edx <- MTRR_PHYS_MASK_HIGH */
wrmsr
- mov $MTRR_PHYS_BASE(1), %ecx
+ find_free_mtrr
+ test %ebx, %ebx
+ jz .halt_forever
+1:
mov $(CONFIG_DCACHE_RAM_BASE + 512 * KiB), %eax
or $MTRR_TYPE_WRBACK, %eax
xor %edx,%edx
wrmsr
- mov $MTRR_PHYS_MASK(1), %ecx
+ incl %ecx
mov $(256 * KiB), %eax /* size mask */
dec %eax
not %eax