Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F115512787
D40058.id123113.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D40058.id123113.diff
View Options
Index: sys/arm64/arm64/pmap.c
===================================================================
--- sys/arm64/arm64/pmap.c
+++ sys/arm64/arm64/pmap.c
@@ -210,15 +210,11 @@
_pa_to_pmdp(vm_paddr_t pa)
{
struct vm_phys_seg *seg;
- int segind;
- for (segind = 0; segind < vm_phys_nsegs; segind++) {
- seg = &vm_phys_segs[segind];
- if (pa >= seg->start && pa < seg->end)
- return ((struct pmap_large_md_page *)seg->md_first +
- pmap_l2_pindex(pa) - pmap_l2_pindex(seg->start));
- }
- return (NULL);
+ if ((seg = vm_phys_paddr_to_seg(pa)) == NULL)
+ return (NULL);
+ return ((struct pmap_large_md_page *)seg->md_first +
+ pmap_l2_pindex(pa) - pmap_l2_pindex(seg->start));
}
static struct pmap_large_md_page *
Index: sys/vm/vm_page.h
===================================================================
--- sys/vm/vm_page.h
+++ sys/vm/vm_page.h
@@ -683,8 +683,6 @@
void vm_page_replace(vm_page_t mnew, vm_object_t object,
vm_pindex_t pindex, vm_page_t mold);
int vm_page_sbusied(vm_page_t m);
-vm_page_t vm_page_scan_contig(u_long npages, vm_page_t m_start,
- vm_page_t m_end, u_long alignment, vm_paddr_t boundary, int options);
vm_page_bits_t vm_page_set_dirty(vm_page_t m);
void vm_page_set_valid_range(vm_page_t m, int base, int size);
vm_offset_t vm_page_startup(vm_offset_t vaddr);
Index: sys/vm/vm_page.c
===================================================================
--- sys/vm/vm_page.c
+++ sys/vm/vm_page.c
@@ -2627,7 +2627,7 @@
* span a hole (or discontiguity) in the physical address space. Both
* "alignment" and "boundary" must be a power of two.
*/
-vm_page_t
+static vm_page_t
vm_page_scan_contig(u_long npages, vm_page_t m_start, vm_page_t m_end,
u_long alignment, vm_paddr_t boundary, int options)
{
@@ -3028,10 +3028,9 @@
int desired_runs)
{
struct vm_domain *vmd;
- vm_paddr_t curr_low;
- vm_page_t m_run, _m_runs[NRUNS], *m_runs;
+ vm_page_t bounds[2], m_run, _m_runs[NRUNS], *m_runs;
u_long count, minalign, reclaimed;
- int error, i, min_reclaim, nruns, options, req_class;
+ int error, i, min_reclaim, nruns, options, req_class, segind;
bool ret;
KASSERT(npages > 0, ("npages is 0"));
@@ -3098,16 +3097,17 @@
* Find the highest runs that satisfy the given constraints
* and restrictions, and record them in "m_runs".
*/
- curr_low = low;
count = 0;
- for (;;) {
- m_run = vm_phys_scan_contig(domain, npages, curr_low,
- high, alignment, boundary, options);
- if (m_run == NULL)
- break;
- curr_low = VM_PAGE_TO_PHYS(m_run) + ptoa(npages);
- m_runs[RUN_INDEX(count, nruns)] = m_run;
- count++;
+ segind = vm_phys_lookup_segind(low);
+ while ((segind = vm_phys_find_range(bounds, segind, domain,
+ npages, low, high)) != -1) {
+ while ((m_run = vm_page_scan_contig(npages, bounds[0],
+ bounds[1], alignment, boundary, options))) {
+ bounds[0] = m_run + npages;
+ m_runs[RUN_INDEX(count, nruns)] = m_run;
+ count++;
+ }
+ segind++;
}
/*
Index: sys/vm/vm_phys.h
===================================================================
--- sys/vm/vm_phys.h
+++ sys/vm/vm_phys.h
@@ -42,6 +42,8 @@
#ifdef _KERNEL
+#include <vm/_vm_phys.h>
+
extern vm_paddr_t phys_avail[];
/* Domains must be dense (non-sparse) and zero-based. */
@@ -71,14 +73,14 @@
vm_memattr_t memattr);
void vm_phys_fictitious_unreg_range(vm_paddr_t start, vm_paddr_t end);
vm_page_t vm_phys_fictitious_to_vm_page(vm_paddr_t pa);
+int vm_phys_find_range(vm_page_t bounds[], int segind, int domain,
+ u_long npages, vm_paddr_t low, vm_paddr_t high);
void vm_phys_free_contig(vm_page_t m, u_long npages);
void vm_phys_free_pages(vm_page_t m, int order);
void vm_phys_init(void);
vm_page_t vm_phys_paddr_to_vm_page(vm_paddr_t pa);
void vm_phys_register_domains(int ndomains, struct mem_affinity *affinity,
int *locality);
-vm_page_t vm_phys_scan_contig(int domain, u_long npages, vm_paddr_t low,
- vm_paddr_t high, u_long alignment, vm_paddr_t boundary, int options);
bool vm_phys_unfree_page(vm_page_t m);
int vm_phys_mem_affinity(int f, int t);
void vm_phys_early_add_seg(vm_paddr_t start, vm_paddr_t end);
@@ -106,5 +108,47 @@
#endif
}
+/*
+ * Find the segind for the first segment at or after the given physical address.
+ */
+static inline int
+vm_phys_lookup_segind(vm_paddr_t pa)
+{
+ u_int hi, lo, mid;
+
+ lo = 0;
+ hi = vm_phys_nsegs;
+ while (lo != hi) {
+ /*
+ * for i in [0, lo), segs[i].end <= pa
+ * for i in [hi, nsegs), segs[i].end > pa
+ */
+ mid = lo + (hi - lo) / 2;
+ if (vm_phys_segs[mid].end <= pa)
+ lo = mid + 1;
+ else
+ hi = mid;
+ }
+ return (lo);
+}
+
+/*
+ * Find the segment corresponding to the given physical address.
+ */
+static inline struct vm_phys_seg *
+vm_phys_paddr_to_seg(vm_paddr_t pa)
+{
+ struct vm_phys_seg *seg;
+ int segind;
+
+ segind = vm_phys_lookup_segind(pa);
+ if (segind < vm_phys_nsegs) {
+ seg = &vm_phys_segs[segind];
+ if (pa >= seg->start)
+ return (seg);
+ }
+ return (NULL);
+}
+
#endif /* _KERNEL */
#endif /* !_VM_PHYS_H_ */
Index: sys/vm/vm_phys.c
===================================================================
--- sys/vm/vm_phys.c
+++ sys/vm/vm_phys.c
@@ -898,14 +898,10 @@
vm_phys_paddr_to_vm_page(vm_paddr_t pa)
{
struct vm_phys_seg *seg;
- int segind;
- for (segind = 0; segind < vm_phys_nsegs; segind++) {
- seg = &vm_phys_segs[segind];
- if (pa >= seg->start && pa < seg->end)
- return (&seg->first_page[atop(pa - seg->start)]);
- }
- return (NULL);
+ if ((seg = vm_phys_paddr_to_seg(pa)) == NULL)
+ return (NULL);
+ return (&seg->first_page[atop(pa - seg->start)]);
}
vm_page_t
@@ -1238,55 +1234,33 @@
}
/*
- * Scan physical memory between the specified addresses "low" and "high" for a
- * run of contiguous physical pages that satisfy the specified conditions, and
- * return the lowest page in the run. The specified "alignment" determines
- * the alignment of the lowest physical page in the run. If the specified
- * "boundary" is non-zero, then the run of physical pages cannot span a
- * physical address that is a multiple of "boundary".
- *
- * "npages" must be greater than zero. Both "alignment" and "boundary" must
- * be a power of two.
+ * Identify the first address range within segment segind or greater
+ * that matches the domain, lies within the low/high range, and has
+ * enough pages. Return -1 if there is none.
*/
-vm_page_t
-vm_phys_scan_contig(int domain, u_long npages, vm_paddr_t low, vm_paddr_t high,
- u_long alignment, vm_paddr_t boundary, int options)
+int
+vm_phys_find_range(vm_page_t bounds[], int segind, int domain,
+ u_long npages, vm_paddr_t low, vm_paddr_t high)
{
- vm_paddr_t pa_end;
- vm_page_t m_end, m_run, m_start;
- struct vm_phys_seg *seg;
- int segind;
+ vm_paddr_t pa_end, pa_start;
+ struct vm_phys_seg *end_seg, *seg;
- KASSERT(npages > 0, ("npages is 0"));
- KASSERT(powerof2(alignment), ("alignment is not a power of 2"));
- KASSERT(powerof2(boundary), ("boundary is not a power of 2"));
- if (low >= high)
- return (NULL);
- for (segind = 0; segind < vm_phys_nsegs; segind++) {
- seg = &vm_phys_segs[segind];
+ KASSERT(npages > 0, ("npages is zero"));
+ end_seg = &vm_phys_segs[vm_phys_nsegs];
+ for (seg = &vm_phys_segs[segind]; seg < end_seg; seg++) {
if (seg->domain != domain)
continue;
if (seg->start >= high)
- break;
- if (low >= seg->end)
- continue;
- if (low <= seg->start)
- m_start = seg->first_page;
- else
- m_start = &seg->first_page[atop(low - seg->start)];
- if (high < seg->end)
- pa_end = high;
- else
- pa_end = seg->end;
- if (pa_end - VM_PAGE_TO_PHYS(m_start) < ptoa(npages))
+ return (-1);
+ pa_start = MAX(low, seg->start);
+ pa_end = MIN(high, seg->end);
+ if (pa_end - pa_start < ptoa(npages))
continue;
- m_end = &seg->first_page[atop(pa_end - seg->start)];
- m_run = vm_page_scan_contig(npages, m_start, m_end,
- alignment, boundary, options);
- if (m_run != NULL)
- return (m_run);
+ bounds[0] = &seg->first_page[atop(pa_start - seg->start)];
+ bounds[1] = &seg->first_page[atop(pa_end - seg->start)];
+ return (seg - vm_phys_segs);
}
- return (NULL);
+ return (-1);
}
/*
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Apr 25, 4:44 PM (4 h, 14 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17788873
Default Alt Text
D40058.id123113.diff (8 KB)
Attached To
Mode
D40058: vm: reduce work of reclamation search
Attached
Detach File
Event Timeline
Log In to Comment