mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 01:32:21 +02:00
nouveau/vmm: fix another SPT/LPT race
We've had an unknown Turing issue for a while with page faults since
large pages and compression.
I've got a patch series that syncs all our L2 handling with ogkm and it
made this fault happen more.
After writing a bunch of debugging patches, I spotted an invalid LPT
entry where there should have been a valid one.
A 64K MAP succeeds on a range, but a subsequent SPT put drops SPT refs
across multiple ranges,
We shouldn't assume all ranges where SPTEs go away will have the same
sparse/invalid/valid state, just iterate over each instead and do the
right thing.
Cc: stable@vger.kernel.org
Signed-off-by: Dave Airlie <airlied@redhat.com>
Fixes: d19512f5ab ("nouveau/vmm: start tracking if the LPT PTE is valid. (v6)")
Link: https://patch.msgid.link/20260615044737.3419585-1-airlied@gmail.com
[ Properly format commit message. - Danilo ]
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
(cherry picked from commit d008141ed4ce924167a03d46fbce9ad1fe4efa29)
Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
parent
695255c57f
commit
6763a0aea6
|
|
@ -231,29 +231,26 @@ nvkm_vmm_unref_sptes(struct nvkm_vmm_iter *it, struct nvkm_vmm_pt *pgt,
|
|||
* covered by a number of LPTEs, the LPTEs once again take
|
||||
* control over their address range.
|
||||
*
|
||||
* Determine how many LPTEs need to transition state.
|
||||
* Transition each LPTE individually as each may have a
|
||||
* different target state (sparse, invalid, or valid).
|
||||
*/
|
||||
pgt->pte[ptei].s.spte_valid = false;
|
||||
for (ptes = 1, ptei++; ptei < lpti; ptes++, ptei++) {
|
||||
for (ptei++; ptei < lpti; ptei++) {
|
||||
if (pgt->pte[ptei].s.sptes)
|
||||
break;
|
||||
pgt->pte[ptei].s.spte_valid = false;
|
||||
}
|
||||
|
||||
if (pgt->pte[pteb].s.sparse) {
|
||||
TRA(it, "LPTE %05x: U -> S %d PTEs", pteb, ptes);
|
||||
pair->func->sparse(vmm, pgt->pt[0], pteb, ptes);
|
||||
} else if (!pgt->pte[pteb].s.lpte_valid) {
|
||||
if (pair->func->invalid) {
|
||||
/* If the MMU supports it, restore the LPTE to the
|
||||
* INVALID state to tell the MMU there is no point
|
||||
* trying to fetch the corresponding SPTEs.
|
||||
*/
|
||||
TRA(it, "LPTE %05x: U -> I %d PTEs", pteb, ptes);
|
||||
pair->func->invalid(vmm, pgt->pt[0], pteb, ptes);
|
||||
while (pteb < ptei) {
|
||||
pgt->pte[pteb].s.spte_valid = false;
|
||||
if (pgt->pte[pteb].s.sparse) {
|
||||
TRA(it, "LPTE %05x: U -> S", pteb);
|
||||
pair->func->sparse(vmm, pgt->pt[0], pteb, 1);
|
||||
} else if (!pgt->pte[pteb].s.lpte_valid) {
|
||||
if (pair->func->invalid) {
|
||||
TRA(it, "LPTE %05x: U -> I", pteb);
|
||||
pair->func->invalid(vmm, pgt->pt[0], pteb, 1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
TRA(it, "LPTE %05x: V %d PTEs", pteb, ptes);
|
||||
pteb++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user