[coreboot-gerrit] Patch set updated for coreboot: arch/x86: Configure additional MTRRs to cover specified size

Rizwan Qureshi (rizwan.qureshi@intel.com) gerrit at coreboot.org
Wed Sep 7 09:51:31 CEST 2016


Rizwan Qureshi (rizwan.qureshi at intel.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/16509

-gerrit

commit e8e5b8fbe400fe3eca15f153979ba03c84e6110d
Author: Rizwan Qureshi <rizwan.qureshi at intel.com>
Date:   Tue Sep 6 22:56:59 2016 +0530

    arch/x86: Configure additional MTRRs to cover specified size
    
    In the current implementation of postcar_frame_add_mtrr,
    if provided size is bigger than the base address alignment,
    the alignment is considered as size and covered by the MTRRs
    ignoring the specified size.
    In this case the callee has to make sure that the provided size
    should be smaller or equal to the base address alignment boundary.
    
    To simplify this, utilize additonal MTRRs to cover the entire size
    specified. We reuse the code code from cpu/x86/mtrr/mtrr.c.
    
    Move fls() amd fms() definitions to mtrr.h.
    
    TEST=Build and boot Kunimitsu.
    
    Change-Id: Ie2e88b596f43692169c7d4440b18498a72fcba11
    Signed-off-by: Rizwan Qureshi <rizwan.qureshi at intel.com>
---
 src/arch/x86/postcar_loader.c | 59 +++++++++++++++++++++++++++----------------
 src/cpu/x86/mtrr/mtrr.c       | 24 ------------------
 src/include/cpu/x86/mtrr.h    | 27 ++++++++++++++++++++
 3 files changed, 64 insertions(+), 46 deletions(-)

diff --git a/src/arch/x86/postcar_loader.c b/src/arch/x86/postcar_loader.c
index b5d8db0..d9719ff 100644
--- a/src/arch/x86/postcar_loader.c
+++ b/src/arch/x86/postcar_loader.c
@@ -59,29 +59,44 @@ int postcar_frame_init(struct postcar_frame *pcf, size_t stack_size)
 void postcar_frame_add_mtrr(struct postcar_frame *pcf,
 				uintptr_t addr, size_t size, int type)
 {
-	size_t align;
-
-	if (pcf->num_var_mttrs >= pcf->max_var_mttrs) {
-		printk(BIOS_ERR, "No more variable MTRRs: %d\n",
-			pcf->max_var_mttrs);
-		return;
-	}
-
-	/* Determine address alignment by lowest bit set in address. */
-	align = addr & (addr ^ (addr - 1));
-
-	if (align < size) {
-		printk(BIOS_ERR, "Address (%lx) alignment (%zx) < size (%zx)\n",
-			addr, align, size);
-		size = align;
+	/*
+	 * Utilize additional MTRRs if the specified size is greater than the
+	 * base address alignment.
+	 */
+	while (size != 0) {
+		uint32_t addr_lsb;
+		uint32_t size_msb;
+		uint32_t mtrr_size;
+
+		if (pcf->num_var_mttrs >= pcf->max_var_mttrs) {
+			printk(BIOS_ERR, "No more variable MTRRs: %d\n",
+					pcf->max_var_mttrs);
+			return;
+		}
+
+		addr_lsb = fls(addr);
+		size_msb = fms(size);
+
+		/* All MTRR entries need to have their base aligned to the mask
+		 * size. The maximum size is calculated by a function of the
+		 * min base bit set and maximum size bit set. */
+		if (addr_lsb > size_msb)
+			mtrr_size = 1 << size_msb;
+		else
+			mtrr_size = 1 << addr_lsb;
+
+		printk(BIOS_DEBUG, "MTRR Range: Start=%lx End=%lx (Size %x)\n",
+					addr, addr + mtrr_size, mtrr_size);
+
+		stack_push(pcf, pcf->upper_mask);
+		stack_push(pcf, ~(mtrr_size - 1) | MTRR_PHYS_MASK_VALID);
+		stack_push(pcf, 0);
+		stack_push(pcf, addr | type);
+		pcf->num_var_mttrs++;
+
+		size -= mtrr_size;
+		addr += mtrr_size;
 	}
-
-	/* Push MTRR mask then base -- upper 32-bits then lower 32-bits. */
-	stack_push(pcf, pcf->upper_mask);
-	stack_push(pcf, ~(size - 1) | MTRR_PHYS_MASK_VALID);
-	stack_push(pcf, 0);
-	stack_push(pcf, addr | type);
-	pcf->num_var_mttrs++;
 }
 
 void *postcar_commit_mtrrs(struct postcar_frame *pcf)
diff --git a/src/cpu/x86/mtrr/mtrr.c b/src/cpu/x86/mtrr/mtrr.c
index 8bdc511..8033e79 100644
--- a/src/cpu/x86/mtrr/mtrr.c
+++ b/src/cpu/x86/mtrr/mtrr.c
@@ -92,30 +92,6 @@ static void enable_var_mtrr(unsigned char deftype)
 	wrmsr(MTRR_DEF_TYPE_MSR, msr);
 }
 
-/* fms: find most significant bit set, stolen from Linux Kernel Source. */
-static inline unsigned int fms(unsigned int x)
-{
-	int r;
-
-	__asm__("bsrl %1,%0\n\t"
-	        "jnz 1f\n\t"
-	        "movl $0,%0\n"
-	        "1:" : "=r" (r) : "g" (x));
-	return r;
-}
-
-/* fls: find least significant bit set */
-static inline unsigned int fls(unsigned int x)
-{
-	int r;
-
-	__asm__("bsfl %1,%0\n\t"
-	        "jnz 1f\n\t"
-	        "movl $32,%0\n"
-	        "1:" : "=r" (r) : "g" (x));
-	return r;
-}
-
 #define MTRR_VERBOSE_LEVEL BIOS_NEVER
 
 /* MTRRs are at a 4KiB granularity. Therefore all address calculations can
diff --git a/src/include/cpu/x86/mtrr.h b/src/include/cpu/x86/mtrr.h
index f32bece..79f9890 100644
--- a/src/include/cpu/x86/mtrr.h
+++ b/src/include/cpu/x86/mtrr.h
@@ -84,6 +84,33 @@ void set_var_mtrr(unsigned reg, unsigned base, unsigned size, unsigned type);
 int get_free_var_mtrr(void);
 #endif
 
+#if !defined(__ASSEMBLER__) && !defined(__ROMCC__)
+
+/* fms: find most significant bit set, stolen from Linux Kernel Source. */
+static inline unsigned int fms(unsigned int x)
+{
+	int r;
+
+	__asm__("bsrl %1,%0\n\t"
+	        "jnz 1f\n\t"
+	        "movl $0,%0\n"
+	        "1:" : "=r" (r) : "g" (x));
+	return r;
+}
+
+/* fls: find least significant bit set */
+static inline unsigned int fls(unsigned int x)
+{
+	int r;
+
+	__asm__("bsfl %1,%0\n\t"
+	        "jnz 1f\n\t"
+	        "movl $32,%0\n"
+	        "1:" : "=r" (r) : "g" (x));
+	return r;
+}
+#endif
+
 /* Align up to next power of 2, suitable for ROMCC and assembler too.
  * Range of result 256kB to 128MB is good enough here.
  */



More information about the coreboot-gerrit mailing list