ref: eec55e28c7eda605b071e3158fbedeb62a828438
parent: 32b9b4b6894b363f4e8b9c25f6df8292eb5f8d87
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Mon Jan 29 03:26:42 EST 2018
pc64: fix kmap() and invlpg() flushing tlb once the index wraps arround is not enougth as in use pte's can be speculatively loaded. so instead use invlpg() and explicitely invalidate the tlb of the page mapped. this fixes wired mount cache corruption for reads approaching 2MB which is the size of the KMAP window. invlpg() was broken, using wrong operand type.
--- a/sys/src/9/pc64/l.s
+++ b/sys/src/9/pc64/l.s
@@ -449,11 +449,8 @@
MOVQ BP, AX /* BP set to -1 if traped */
RET
-TEXT invlpg(SB), 1, $-4 /* INVLPG va+0(FP) */
- MOVQ RARG, va+0(FP)
-
- INVLPG va+0(FP)
-
+TEXT invlpg(SB), 1, $-4
+ INVLPG (RARG)
RET
TEXT wbinvd(SB), 1, $-4
--- a/sys/src/9/pc64/mmu.c
+++ b/sys/src/9/pc64/mmu.c
@@ -485,15 +485,13 @@
return (KMap*)KADDR(pa);
x = splhi();
- va = KMAP + ((uintptr)up->kmapindex << PGSHIFT);
+ va = KMAP + (((uintptr)up->kmapindex++ << PGSHIFT) & (KMAPSIZE-1));
pte = mmuwalk(m->pml4, va, 0, 1);
- if(pte == 0 || *pte & PTEVALID)
+ if(pte == 0 || (*pte & PTEVALID) != 0)
panic("kmap: pa=%#p va=%#p", pa, va);*pte = pa | PTEWRITE|PTEVALID;
- up->kmapindex = (up->kmapindex + 1) % (1<<PTSHIFT);
- if(up->kmapindex == 0)
- mmuflushtlb();
splx(x);
+ invlpg(va);
return (KMap*)va;
}
--
⑨