Make two runs of MTRR setting when setting memory ranges to write-back. At the

first run only set up uncacheable MTRRs and in the second run set the write-back
ones up. If this order is not followed, we could set too large ranges to
cacheable first and then limit it back to uncacheable later. On systems with
enough physical memory this would lead to a temporary situation in which areas
become cacheable that must not be, resulting in system hangs or other unexpected
behaviour. Fixes last part of #4018.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31027 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz 2009-06-13 11:40:05 +00:00
parent 96b24aef3f
commit f835a75f31

View File

@ -272,33 +272,48 @@ set_memory_write_back(int32 id, uint64 base, uint64 length)
#ifdef TRACE_MTRR
dprintf("solutions: ");
for (int i=0; i<sSolutionCount; i++) {
dprintf("0x%Lx ", sSolutions[i]);
}
dprintf("\n");
for (int i=0; i<sSolutionCount; i++)
dprintf("0x%Lx ", sSolutions[i]);
dprintf("\n");
#endif
bool nextDown = false;
for (int i = 0; i < sSolutionCount; i++) {
if (sSolutions[i] < 0) {
if (nextDown)
base += sSolutions[i];
err = set_memory_type(id, base, -sSolutions[i], nextDown ? B_MTR_UC : B_MTR_WB);
if (err != B_OK) {
dprintf("set_memory_type returned %s (0x%lx)\n", strerror(err), err);
for (int run = 0; run < 2; run++) {
bool nextDown = false;
uint64 newBase = base;
for (int i = 0; i < sSolutionCount; i++) {
if (sSolutions[i] < 0) {
if (nextDown)
newBase += sSolutions[i];
if ((run == 0) == nextDown) {
err = set_memory_type(id, newBase, -sSolutions[i],
nextDown ? B_MTR_UC : B_MTR_WB);
if (err != B_OK) {
dprintf("set_memory_type returned %s (0x%lx)\n",
strerror(err), err);
}
}
if (!nextDown)
newBase -= sSolutions[i];
nextDown = !nextDown;
} else {
if (nextDown)
newBase -= sSolutions[i];
if ((run == 0) == nextDown) {
err = set_memory_type(id, newBase, sSolutions[i],
nextDown ? B_MTR_UC : B_MTR_WB);
if (err != B_OK) {
dprintf("set_memory_type returned %s (0x%lx)\n",
strerror(err), err);
}
}
if (!nextDown)
newBase += sSolutions[i];
}
if (!nextDown)
base -= sSolutions[i];
nextDown = !nextDown;
} else {
if (nextDown)
base -= sSolutions[i];
err = set_memory_type(id, base, sSolutions[i], nextDown ? B_MTR_UC : B_MTR_WB);
if (err != B_OK) {
dprintf("set_memory_type returned %s (0x%lx)\n", strerror(err), err);
}
if (!nextDown)
base += sSolutions[i];
}
}
}