]> xenbits.xensource.com Git - people/julieng/freebsd.git/commitdiff
pmap_change_attr: Only fixup DMAP for DMAPed ranges
authorcem <cem@FreeBSD.org>
Thu, 29 Oct 2015 19:07:00 +0000 (19:07 +0000)
committercem <cem@FreeBSD.org>
Thu, 29 Oct 2015 19:07:00 +0000 (19:07 +0000)
pmap_change_attr must change the memory type of both the requested KVA
and the corresponding DMAP mappings (if such mappings exist), to satisfy
an Intel requirement that two or more mappings to the same physical
pages must have the same memory type.

However, not all kernel mapped pages have corresponding DMAP mappings --
for example, 64-bit BARs.  Skip fixing up the DMAP for out-of-bounds
addresses.

Submitted by: Steve Wahl <steve_wahl@dell.com>
Reviewed by: alc, jhb
Sponsored by: Dell Compellent
Differential Revision: https://reviews.freebsd.org/D4030

sys/amd64/amd64/pmap.c

index 94a7d0c9640142810b158ab183832293ac795c96..883c1c5f4fef778e0f368ad6484749b15000144f 100644 (file)
@@ -6411,7 +6411,7 @@ pmap_change_attr_locked(vm_offset_t va, vm_size_t size, int mode)
         */
        for (tmpva = base; tmpva < base + size; ) {
                pdpe = pmap_pdpe(kernel_pmap, tmpva);
-               if (*pdpe == 0)
+               if (pdpe == NULL || *pdpe == 0)
                        return (EINVAL);
                if (*pdpe & PG_PS) {
                        /*
@@ -6484,7 +6484,8 @@ pmap_change_attr_locked(vm_offset_t va, vm_size_t size, int mode)
                                    X86_PG_PDE_CACHE);
                                changed = TRUE;
                        }
-                       if (tmpva >= VM_MIN_KERNEL_ADDRESS) {
+                       if (tmpva >= VM_MIN_KERNEL_ADDRESS &&
+                           (*pdpe & PG_PS_FRAME) < dmaplimit) {
                                if (pa_start == pa_end) {
                                        /* Start physical address run. */
                                        pa_start = *pdpe & PG_PS_FRAME;
@@ -6513,7 +6514,8 @@ pmap_change_attr_locked(vm_offset_t va, vm_size_t size, int mode)
                                    X86_PG_PDE_CACHE);
                                changed = TRUE;
                        }
-                       if (tmpva >= VM_MIN_KERNEL_ADDRESS) {
+                       if (tmpva >= VM_MIN_KERNEL_ADDRESS &&
+                           (*pde & PG_PS_FRAME) < dmaplimit) {
                                if (pa_start == pa_end) {
                                        /* Start physical address run. */
                                        pa_start = *pde & PG_PS_FRAME;
@@ -6540,7 +6542,8 @@ pmap_change_attr_locked(vm_offset_t va, vm_size_t size, int mode)
                                    X86_PG_PTE_CACHE);
                                changed = TRUE;
                        }
-                       if (tmpva >= VM_MIN_KERNEL_ADDRESS) {
+                       if (tmpva >= VM_MIN_KERNEL_ADDRESS &&
+                           (*pte & PG_PS_FRAME) < dmaplimit) {
                                if (pa_start == pa_end) {
                                        /* Start physical address run. */
                                        pa_start = *pte & PG_FRAME;