cpu/x86/mtrr: fail early if solution exceeds available MTRRs

If an MTRR solution exceeds the number of available MTRRs
don't attempt to commit the result. It will just GP fault
with the MSR write to an invalid MSR address.

Change-Id: I5c4912d5244526544c299c3953bca1bf884b34d5
Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: https://review.coreboot.org/20163
Reviewed-by: Youness Alaoui <snifikino@gmail.com>
Reviewed-by: Furquan Shaikh <furquan@google.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Philippe Mathieu-Daudé <philippe.mathieu.daude@gmail.com>
diff --git a/src/cpu/x86/mtrr/mtrr.c b/src/cpu/x86/mtrr/mtrr.c
index e7c69be..609d1e7 100644
--- a/src/cpu/x86/mtrr/mtrr.c
+++ b/src/cpu/x86/mtrr/mtrr.c
@@ -751,10 +751,16 @@
 	sol->num_used = var_state.mtrr_index;
 }
 
-static void commit_var_mtrrs(const struct var_mtrr_solution *sol)
+static int commit_var_mtrrs(const struct var_mtrr_solution *sol)
 {
 	int i;
 
+	if (sol->num_used > total_mtrrs) {
+		printk(BIOS_WARNING, "Not enough MTRRs: %d vs %d\n",
+			sol->num_used, total_mtrrs);
+		return -1;
+	}
+
 	/* Write out the variable MTRRs. */
 	disable_cache();
 	for (i = 0; i < sol->num_used; i++) {
@@ -767,6 +773,7 @@
 	enable_var_mtrr(sol->mtrr_default_type);
 	enable_cache();
 
+	return 0;
 }
 
 void x86_setup_var_mtrrs(unsigned int address_bits, unsigned int above4gb)
@@ -872,10 +879,15 @@
 		calc_var_mtrrs(&addr_space, above4gb, address_bits);
 	prepare_var_mtrrs(&addr_space, sol.mtrr_default_type,
 				above4gb, address_bits, &sol);
-	commit_var_mtrrs(&sol);
+
+	if (commit_var_mtrrs(&sol) < 0)
+		printk(BIOS_WARNING, "Unable to insert temporary MTRR range: 0x%016llx - 0x%016llx size 0x%08llx type %d\n",
+			(long long)begin, (long long)begin + size,
+			(long long)size, type);
+	else
+		put_back_original_solution = true;
 
 	memranges_teardown(&addr_space);
-	put_back_original_solution = true;
 }
 
 static void remove_temp_solution(void *unused)