Index: sys/arch/amd64/amd64/machdep.c =================================================================== RCS file: /cvsroot/src/sys/arch/amd64/amd64/machdep.c,v retrieving revision 1.243 diff -u -r1.243 machdep.c --- sys/arch/amd64/amd64/machdep.c 23 Dec 2016 07:15:27 -0000 1.243 +++ sys/arch/amd64/amd64/machdep.c 26 Dec 2016 11:19:10 -0000 @@ -1468,30 +1468,39 @@ static void init_x86_64_msgbuf(void) { - /* Message buffer is located at end of core. */ - psize_t reqsz = round_page(MSGBUFSIZE); - psize_t sz = 0; - - for (sz = 0; sz < reqsz; sz += PAGE_SIZE) { - paddr_t stolenpa; - - if (!uvm_page_physget(&stolenpa)) - break; - - if (stolenpa == (msgbuf_p_seg[msgbuf_p_cnt].paddr - + PAGE_SIZE)) { - /* contiguous: append it to current buf alloc */ - msgbuf_p_seg[msgbuf_p_cnt].sz += PAGE_SIZE; - } else { - /* non-contiguous: start a new msgbuf seg */ - msgbuf_p_seg[msgbuf_p_cnt].sz = PAGE_SIZE; - msgbuf_p_seg[msgbuf_p_cnt++].paddr = stolenpa; - } + /* Message buffer is located at end of core. */ + psize_t sz = round_page(MSGBUFSIZE); + psize_t reqsz = sz; + uvm_physseg_t x; + + search_again: + x = uvm_physseg_get_last(); + + /* Shrink so it'll fit in the last segment. */ + if (uvm_physseg_get_avail_end(x) - uvm_physseg_get_avail_start(x) < atop(sz)) + sz = ctob(uvm_physseg_get_avail_end(x) - uvm_physseg_get_avail_start(x)); + + uvm_physseg_unplug(uvm_physseg_get_end(x) - atop(sz), atop(sz)); + msgbuf_p_seg[msgbuf_p_cnt].sz = sz; + msgbuf_p_seg[msgbuf_p_cnt++].paddr = ctob(uvm_physseg_get_avail_end(x)); + + /* Now find where the new avail_end is. */ + avail_end = ctob(uvm_physseg_get_avail_end(x)); + + if (sz == reqsz) + return; + + reqsz -= sz; + + if (msgbuf_p_cnt == VM_PHYSSEG_MAX) { + /* No more segments available, bail out. */ + printf("WARNING: MSGBUFSIZE (%zu) too large, using %zu.\n", + (size_t)MSGBUFSIZE, (size_t)(MSGBUFSIZE - reqsz)); + return; } - if (sz != reqsz) - printf("%s: could only allocate %ld bytes of requested %ld bytes\n", - __func__, sz, reqsz); + sz = reqsz; + goto search_again; } static void