shithub: riscv

Download patch

ref: 6cc223ee56e5f0aa20dfc6f51b70607b5b14cf5f
parent: 0ba91ae22a06af3a7561db15973dd98f715cc9eb
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Wed Nov 4 18:08:52 EST 2020

pc/pc64: fix faulty mtrr slot reuse (thanks Fulton)

The change 3306:c5cf77167bfe made the code reuse MTRR slots
of the default memory type.

But this did not take overlapping ranges into account!

If two or more variable-range MTRRs overlap, the following rules apply:

a.	If the memory types are identical, then that memory type is used.
b.	If at least one of the memory types is UC, then UC memory type is used.
c.	If at least of of the memory types is WT. and the only other memory type
	is WB, then th WT memory type is used.
d.	If the combination of memory types is not listed above,
	then the memory type used in undefined.

It so happend that on a Dell Latitude E7450 that the BIOS defines
the default type as UC. and the first slot defines a 16GB range
of type WB. Then the rest of the ranges mark the PCI space back
as UC, but overlapping the first WB range! This works because
of rule (B) above.

When trying to make the framebuffer write-combining, we would
falsely reuse one of the UC sub-ranges and making the UC memory
into WB as a side effect.

Thanks to Fulton for his patience and providing debug logs and
doing experiments for us to narrow the problem down.

--- a/sys/src/9/pc/mtrr.c
+++ b/sys/src/9/pc/mtrr.c
@@ -292,7 +292,7 @@
 	slot = -1;
 	for(i = 0; i < vcnt; i++){
 		mok = mtrrdec(&mtrreg[i], &mp, &msize, &mtype);
-		if(slot == -1 && (!mok || mtype == (def & Deftype)))
+		if(slot == -1 && !mok)
 			slot = i;	/* good, but look further for exact match */
 		if(mok && mp == base && msize == size){
 			slot = i;