The branch main has been updated by dougm:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=da92ecbc0d8f4652cd5c97aace290103055c7019

commit da92ecbc0d8f4652cd5c97aace290103055c7019
Author:     Doug Moore <[email protected]>
AuthorDate: 2022-01-18 18:32:46 +0000
Commit:     Doug Moore <[email protected]>
CommitDate: 2022-01-18 18:49:09 +0000

    vm_phys: fix seg->end test in alloc_seg_contig
    
    In vm_phys_alloc_seg_contig, in allocating multiple memory blocks for
    a huge allocation, ensure that the end of the allocated range does not
    exceed the upper segment limit.
    
    Reorder a couple of checks to improve code layout.
    
    Reviewed by:    alc
    MFC after:      1 week
    Differential Revision:  https://reviews.freebsd.org/D33870
---
 sys/vm/vm_phys.c | 69 +++++++++++++++++++++++++++-----------------------------
 1 file changed, 33 insertions(+), 36 deletions(-)

diff --git a/sys/vm/vm_phys.c b/sys/vm/vm_phys.c
index 6798c55cc91c..a880b7abd324 100644
--- a/sys/vm/vm_phys.c
+++ b/sys/vm/vm_phys.c
@@ -1428,47 +1428,44 @@ vm_phys_alloc_seg_contig(struct vm_phys_seg *seg, 
u_long npages,
                        fl = (*seg->free_queues)[pind];
                        TAILQ_FOREACH(m_ret, &fl[oind].pl, listq) {
                                /*
-                                * Is the size of this allocation request
-                                * larger than the largest block size?
+                                * Determine if the address range starting at pa
+                                * is within the given range, satisfies the
+                                * given alignment, and does not cross the given
+                                * boundary.
                                 */
-                               if (order >= VM_NFREEORDER) {
-                                       /*
-                                        * Determine if a sufficient number of
-                                        * subsequent blocks to satisfy the
-                                        * allocation request are free.
-                                        */
-                                       pa = VM_PAGE_TO_PHYS(m_ret);
-                                       pa_end = pa + size;
-                                       if (pa_end < pa)
-                                               continue;
-                                       for (;;) {
-                                               pa += 1 << (PAGE_SHIFT +
-                                                   VM_NFREEORDER - 1);
-                                               if (pa >= pa_end ||
-                                                   pa < seg->start ||
-                                                   pa >= seg->end)
-                                                       break;
-                                               m = &seg->first_page[atop(pa -
-                                                   seg->start)];
-                                               if (m->order != VM_NFREEORDER -
-                                                   1)
-                                                       break;
-                                       }
-                                       /* If not, go to the next block. */
-                                       if (pa < pa_end)
-                                               continue;
-                               }
+                               pa = VM_PAGE_TO_PHYS(m_ret);
+                               pa_end = pa + size;
+                               if (pa < low || pa_end > high ||
+                                   !vm_addr_ok(pa, size, alignment, boundary))
+                                       continue;
 
                                /*
-                                * Determine if the blocks are within the
-                                * given range, satisfy the given alignment,
-                                * and do not cross the given boundary.
+                                * Is the size of this allocation request
+                                * no more than the largest block size?
                                 */
-                               pa = VM_PAGE_TO_PHYS(m_ret);
-                               pa_end = pa + size;
-                               if (pa >= low && pa_end <= high &&
-                                   vm_addr_ok(pa, size, alignment, boundary))
+                               if (order < VM_NFREEORDER)
                                        goto done;
+
+                               /*
+                                * Determine if the address range is valid
+                                * (without overflow in pa_end calculation)
+                                * and fits within the segment.
+                                */
+                               if (pa_end < pa || pa_end > seg->end)
+                                       continue;
+
+                               /*
+                                * Determine if a sufficient number of
+                                * subsequent blocks to satisfy the
+                                * allocation request are free.
+                                */
+                               do {
+                                       pa += 1 <<
+                                           (PAGE_SHIFT + VM_NFREEORDER - 1);
+                                       if (pa >= pa_end)
+                                               goto done;
+                               } while (VM_NFREEORDER - 1 == seg->first_page[
+                                   atop(pa - seg->start)].order);
                        }
                }
        }

Reply via email to