[coreboot-gerrit] New patch to review for coreboot: arch/x86: Configure additional MTRRs to cover specified size.

Rizwan Qureshi (rizwan.qureshi@intel.com) gerrit at coreboot.org
Tue Sep 6 19:55:40 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 5f36423d2a43a2846e3a7622fc025e0924c4dc36
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 adress aligment boundary.
    
    To simplify this, implement an algorithm to utilize additonal MTRRs
    to cover the entire size specified.
    
    TEST: Build and Boot Kunimitsu.
    
    Change-Id: Ie2e88b596f43692169c7d4440b18498a72fcba11
    Signed-off-by: Rizwan Qureshi <rizwan.qureshi at intel.com>
---
 src/arch/x86/postcar_loader.c | 81 ++++++++++++++++++++++++++++++++-----------
 1 file changed, 60 insertions(+), 21 deletions(-)

diff --git a/src/arch/x86/postcar_loader.c b/src/arch/x86/postcar_loader.c
index b5d8db0..7500d14 100644
--- a/src/arch/x86/postcar_loader.c
+++ b/src/arch/x86/postcar_loader.c
@@ -59,29 +59,68 @@ 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;
+	size_t align, tsize, total_span = size;
 
-	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 aligment.
+	 * 1. Get alignment and remaining size to cache, initially it is
+	 *    equal to provided size.
+	 * 2. If aligment is bigger than remaining size then,
+	 *     Configure a MTRR for this base and size.
+	 *     Adjust remaing size and base address.
+	 *     jump to step 1.
+	 * 3. Else If remaining size is bigger then,
+	 *     Determine the biggest 2^N part of it and,
+	 *     Configure a MTRR for this base and size.
+	 *     Adjust remaing size and base address.
+	 * 	   jump to step 1.
+	 * 4. Stop when we run out of MTRRs or the whole span has been
+	 *    accounted for in MTRRs.
+	 */
+	while (total_span){
+
+		if (pcf->num_var_mttrs >= pcf->max_var_mttrs) {
+			printk(BIOS_ERR, "No more variable MTRRs: %d\n",
+					pcf->max_var_mttrs);
+			return;
+		}
+
+		align = addr & (addr ^ (addr - 1));
+		if (align >= total_span){
+			printk(BIOS_DEBUG, "MTRR Range : Start: %lx End: %zx (Size %zx)\n",
+				addr, addr + total_span, total_span);
+
+			stack_push(pcf, pcf->upper_mask);
+			stack_push(pcf, ~(total_span - 1) | MTRR_PHYS_MASK_VALID);
+			stack_push(pcf, 0);
+			stack_push(pcf, addr | type);
+			pcf->num_var_mttrs++;
+
+			total_span -= total_span;
+			addr += total_span;
+		}else if (align < total_span){
+			/* get the largest "power of 2 chunk" in size */
+			tsize = total_span - 1;
+			tsize |= tsize >> 1;
+			tsize |= tsize >> 2;
+			tsize |= tsize >> 4;
+			tsize |= tsize >> 8;
+			tsize |= tsize >> 16;
+			tsize = ((tsize + 1) >> 1);
+			printk(BIOS_DEBUG, "MTRR Range : Start: %lx End: %lx (Size %zx)\n",
+				addr, addr + tsize, tsize);
+
+			stack_push(pcf, pcf->upper_mask);
+			stack_push(pcf, ~(tsize - 1) | MTRR_PHYS_MASK_VALID);
+			stack_push(pcf, 0);
+			stack_push(pcf, addr | type);
+			pcf->num_var_mttrs++;
+
+			total_span -= tsize;
+			addr += tsize;
+		}
 	}
-
-	/* 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)



More information about the coreboot-gerrit mailing list