mirror of
https://github.com/freebsd/freebsd-src
synced 2024-07-22 10:48:02 +00:00
rangeset: add next() iteration
Add a method rangeset_next to find the first range that starts at or after a given value. Use it to rewrite pmap_pkru_same and pmap_bti_same to avoid walking a page at a time over pages in no range. Reviewed by: andrew, kib Differential Revision: https://reviews.freebsd.org/D45511
This commit is contained in:
parent
1b13e36fcc
commit
2c10bacdf4
|
@ -11448,7 +11448,7 @@ pmap_pkru_deassign_all(pmap_t pmap)
|
|||
static bool
|
||||
pmap_pkru_same(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
|
||||
{
|
||||
struct pmap_pkru_range *ppr, *prev_ppr;
|
||||
struct pmap_pkru_range *next_ppr, *ppr;
|
||||
vm_offset_t va;
|
||||
|
||||
PMAP_LOCK_ASSERT(pmap, MA_OWNED);
|
||||
|
@ -11457,19 +11457,19 @@ pmap_pkru_same(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
|
|||
sva >= VM_MAXUSER_ADDRESS)
|
||||
return (true);
|
||||
MPASS(eva <= VM_MAXUSER_ADDRESS);
|
||||
for (va = sva; va < eva; prev_ppr = ppr) {
|
||||
ppr = rangeset_lookup(&pmap->pm_pkru, va);
|
||||
if (va == sva)
|
||||
prev_ppr = ppr;
|
||||
else if ((ppr == NULL) ^ (prev_ppr == NULL))
|
||||
ppr = rangeset_lookup(&pmap->pm_pkru, sva);
|
||||
if (ppr == NULL) {
|
||||
ppr = rangeset_next(&pmap->pm_pkru, sva);
|
||||
return (ppr == NULL ||
|
||||
ppr->pkru_rs_el.re_start >= eva);
|
||||
}
|
||||
while ((va = ppr->pkru_rs_el.re_end) < eva) {
|
||||
next_ppr = rangeset_next(&pmap->pm_pkru, va);
|
||||
if (next_ppr == NULL ||
|
||||
va != next_ppr->pkru_rs_el.re_start ||
|
||||
ppr->pkru_keyidx != next_ppr->pkru_keyidx)
|
||||
return (false);
|
||||
if (ppr == NULL) {
|
||||
va += PAGE_SIZE;
|
||||
continue;
|
||||
}
|
||||
if (prev_ppr->pkru_keyidx != ppr->pkru_keyidx)
|
||||
return (false);
|
||||
va = ppr->pkru_rs_el.re_end;
|
||||
ppr = next_ppr;
|
||||
}
|
||||
return (true);
|
||||
}
|
||||
|
|
|
@ -9274,7 +9274,7 @@ pmap_bti_deassign_all(pmap_t pmap)
|
|||
static bool
|
||||
pmap_bti_same(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
|
||||
{
|
||||
struct rs_el *prev_rs, *rs;
|
||||
struct rs_el *next_rs, *rs;
|
||||
vm_offset_t va;
|
||||
|
||||
PMAP_LOCK_ASSERT(pmap, MA_OWNED);
|
||||
|
@ -9286,17 +9286,18 @@ pmap_bti_same(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
|
|||
if (pmap->pm_bti == NULL || ADDR_IS_KERNEL(sva))
|
||||
return (true);
|
||||
MPASS(!ADDR_IS_KERNEL(eva));
|
||||
for (va = sva; va < eva; prev_rs = rs) {
|
||||
rs = rangeset_lookup(pmap->pm_bti, va);
|
||||
if (va == sva)
|
||||
prev_rs = rs;
|
||||
else if ((rs == NULL) ^ (prev_rs == NULL))
|
||||
rs = rangeset_lookup(pmap->pm_bti, sva);
|
||||
if (rs == NULL) {
|
||||
rs = rangeset_next(pmap->pm_bti, sva);
|
||||
return (rs == NULL ||
|
||||
rs->re_start >= eva);
|
||||
}
|
||||
while ((va = rs->re_end) < eva) {
|
||||
next_rs = rangeset_next(pmap->pm_bti, va);
|
||||
if (next_rs == NULL ||
|
||||
va != next_rs->re_start)
|
||||
return (false);
|
||||
if (rs == NULL) {
|
||||
va += PAGE_SIZE;
|
||||
continue;
|
||||
}
|
||||
va = rs->re_end;
|
||||
rs = next_rs;
|
||||
}
|
||||
return (true);
|
||||
}
|
||||
|
|
|
@ -260,6 +260,14 @@ rangeset_lookup(struct rangeset *rs, uint64_t place)
|
|||
return (r);
|
||||
}
|
||||
|
||||
void *
|
||||
rangeset_next(struct rangeset *rs, uint64_t place)
|
||||
{
|
||||
|
||||
rangeset_check(rs);
|
||||
return (RANGESET_PCTRIE_LOOKUP_GE(&rs->rs_trie, place));
|
||||
}
|
||||
|
||||
int
|
||||
rangeset_copy(struct rangeset *dst_rs, struct rangeset *src_rs)
|
||||
{
|
||||
|
|
|
@ -74,6 +74,11 @@ int rangeset_remove_pred(struct rangeset *rs, uint64_t start,
|
|||
*/
|
||||
void *rangeset_lookup(struct rangeset *rs, uint64_t place);
|
||||
|
||||
/*
|
||||
* Finds the first range that begins at or after place.
|
||||
*/
|
||||
void *rangeset_next(struct rangeset *rs, uint64_t place);
|
||||
|
||||
/*
|
||||
* Copies src_rs entries into dst_rs. dst_rs must be empty.
|
||||
* Leaves dst_rs empty on failure.
|
||||
|
|
Loading…
Reference in a new issue