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 (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);
+ } 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);
+ }
+ } else {
+ TRA(it, "LPTE %05x: V %d PTEs", pteb, ptes);
}
}
}
if (desc->type == SPT && (pgt->refs[0] || pgt->refs[1]))
nvkm_vmm_unref_sptes(it, pgt, desc, ptei, ptes);
+ if (desc->type == LPT && (pgt->refs[0] || pgt->refs[1])) {
+ for (u32 lpti = ptei; ptes; lpti++) {
+ pgt->pte[lpti].s.lptes--;
+ if (pgt->pte[lpti].s.lptes == 0)
+ pgt->pte[lpti].s.lpte_valid = false;
+ ptes--;
+ }
+ }
+
/* PT no longer needed? Destroy it. */
if (!pgt->refs[type]) {
it->lvl++;
* Determine how many LPTEs need to transition state.
*/
pgt->pte[ptei].s.spte_valid = true;
+ pgt->pte[ptei].s.lpte_valid = false;
for (ptes = 1, ptei++; ptei < lpti; ptes++, ptei++) {
if (pgt->pte[ptei].s.spte_valid)
break;
pgt->pte[ptei].s.spte_valid = true;
+ pgt->pte[ptei].s.lpte_valid = false;
}
if (pgt->pte[pteb].s.sparse) {
if (desc->type == SPT)
nvkm_vmm_ref_sptes(it, pgt, desc, ptei, ptes);
+ if (desc->type == LPT) {
+ for (u32 lpti = ptei; ptes; lpti++) {
+ pgt->pte[lpti].s.spte_valid = false;
+ pgt->pte[lpti].s.lpte_valid = true;
+ pgt->pte[lpti].s.lptes++;
+ ptes--;
+ }
+ }
+
return true;
}