summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>2002-07-08 00:17:43 +0000
committerpeter <peter@FreeBSD.org>2002-07-08 00:17:43 +0000
commitd67ae5f23f51adbdba955a259dd097c0d690715b (patch)
treec6cc831ed7c561cfc4c86386f0f5ffb423047cbd
parente06b8c244d38f8b7bff6834d9ba38b6dac296cf1 (diff)
downloadFreeBSD-src-d67ae5f23f51adbdba955a259dd097c0d690715b.zip
FreeBSD-src-d67ae5f23f51adbdba955a259dd097c0d690715b.tar.gz
Fix a hideous TLB bug. pmap_unmapdev neglected to remove the device
mappings from the page tables, which were mapped with PG_G! We could reuse the page table entry for another mapping (pmap_mapdev) but it would never have cleared any remaining PG_G TLB entries.
-rw-r--r--sys/amd64/amd64/pmap.c27
-rw-r--r--sys/i386/i386/pmap.c27
2 files changed, 46 insertions, 8 deletions
diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
index 9e3c6c3..a0c8ebe 100644
--- a/sys/amd64/amd64/pmap.c
+++ b/sys/amd64/amd64/pmap.c
@@ -3139,15 +3139,21 @@ pmap_mapdev(pa, size)
panic("pmap_mapdev: Couldn't alloc kernel virtual memory");
pa = pa & PG_FRAME;
- for (tmpva = va; size > 0;) {
+ for (tmpva = va; size > 0; ) {
pte = vtopte(tmpva);
*pte = pa | PG_RW | PG_V | pgeflag;
+#ifdef SMP
+ cpu_invlpg((void *)tmpva);
+#else
+ invltlb_1pg(tmpva);
+#endif
size -= PAGE_SIZE;
tmpva += PAGE_SIZE;
pa += PAGE_SIZE;
}
- invltlb();
-
+#ifdef SMP
+ smp_invltlb();
+#endif
return ((void *)(va + offset));
}
@@ -3156,11 +3162,24 @@ pmap_unmapdev(va, size)
vm_offset_t va;
vm_size_t size;
{
- vm_offset_t base, offset;
+ vm_offset_t base, offset, tmpva;
+ pt_entry_t *pte;
base = va & PG_FRAME;
offset = va & PAGE_MASK;
size = roundup(offset + size, PAGE_SIZE);
+ for (tmpva = base; tmpva < (base + size); tmpva += PAGE_SIZE) {
+ pte = vtopte(tmpva);
+ *pte = 0;
+#ifdef SMP
+ cpu_invlpg((void *)tmpva);
+#else
+ invltlb_1pg(tmpva);
+#endif
+ }
+#ifdef SMP
+ smp_invltlb();
+#endif
kmem_free(kernel_map, base, size);
}
diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c
index 9e3c6c3..a0c8ebe 100644
--- a/sys/i386/i386/pmap.c
+++ b/sys/i386/i386/pmap.c
@@ -3139,15 +3139,21 @@ pmap_mapdev(pa, size)
panic("pmap_mapdev: Couldn't alloc kernel virtual memory");
pa = pa & PG_FRAME;
- for (tmpva = va; size > 0;) {
+ for (tmpva = va; size > 0; ) {
pte = vtopte(tmpva);
*pte = pa | PG_RW | PG_V | pgeflag;
+#ifdef SMP
+ cpu_invlpg((void *)tmpva);
+#else
+ invltlb_1pg(tmpva);
+#endif
size -= PAGE_SIZE;
tmpva += PAGE_SIZE;
pa += PAGE_SIZE;
}
- invltlb();
-
+#ifdef SMP
+ smp_invltlb();
+#endif
return ((void *)(va + offset));
}
@@ -3156,11 +3162,24 @@ pmap_unmapdev(va, size)
vm_offset_t va;
vm_size_t size;
{
- vm_offset_t base, offset;
+ vm_offset_t base, offset, tmpva;
+ pt_entry_t *pte;
base = va & PG_FRAME;
offset = va & PAGE_MASK;
size = roundup(offset + size, PAGE_SIZE);
+ for (tmpva = base; tmpva < (base + size); tmpva += PAGE_SIZE) {
+ pte = vtopte(tmpva);
+ *pte = 0;
+#ifdef SMP
+ cpu_invlpg((void *)tmpva);
+#else
+ invltlb_1pg(tmpva);
+#endif
+ }
+#ifdef SMP
+ smp_invltlb();
+#endif
kmem_free(kernel_map, base, size);
}
OpenPOWER on IntegriCloud