-
Notifications
You must be signed in to change notification settings - Fork 61
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
several caprevoke optimizations #2195
Open
markjdb
wants to merge
3
commits into
CTSRD-CHERI:dev
Choose a base branch
from
markjdb:dev-caprevoke-optimizations
base: dev
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 1 commit
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -67,7 +67,8 @@ | |
|
||
static void vm_cheri_revoke_pass_pre(vm_map_t); | ||
static void vm_cheri_revoke_pass_post(vm_map_t); | ||
static int vm_cheri_revoke_pass_locked(const struct vm_cheri_revoke_cookie *); | ||
static int vm_cheri_revoke_pass_locked(struct vmspace *, | ||
const struct vm_cheri_revoke_cookie *); | ||
|
||
static SYSCTL_NODE(_vm_stats, OID_AUTO, cheri_revoke, | ||
CTLFLAG_RD | CTLFLAG_MPSAFE, 0, | ||
|
@@ -84,15 +85,20 @@ | |
"Number of VM map re-lookups"); | ||
|
||
static COUNTER_U64_DEFINE_EARLY(cheri_skip_prot_no_readcap); | ||
SYSCTL_COUNTER_U64(_vm_stats_cheri_revoke, OID_AUTO, skip_prot_no_readcap, CTLFLAG_RD, | ||
&cheri_skip_prot_no_readcap, | ||
"Virtual pages skipped in map entries without readcap permission"); | ||
|
||
static COUNTER_U64_DEFINE_EARLY(cheri_skip_obj_no_hascap); | ||
SYSCTL_COUNTER_U64(_vm_stats_cheri_revoke, OID_AUTO, skip_obj_no_hascap, CTLFLAG_RD, | ||
&cheri_skip_obj_no_hascap, | ||
"Virtual pages skipped in VM objects with no capabilities"); | ||
|
||
static COUNTER_U64_DEFINE_EARLY(cheri_last_ref_early_finish); | ||
SYSCTL_COUNTER_U64(_vm_stats_cheri_revoke, OID_AUTO, last_ref_early_finish, CTLFLAG_RD, | ||
&cheri_last_ref_early_finish, | ||
"Scans finished early because the target exited"); | ||
|
||
/***************************** KERNEL THREADS ***************************/ | ||
|
||
static MALLOC_DEFINE(M_REVOKE, "cheri_revoke", "cheri_revoke temporary data"); | ||
|
@@ -182,6 +188,7 @@ | |
mtx_unlock(&async_revoke_mtx); | ||
|
||
vmspace_switch_aio(arc->vm); | ||
vmspace_free(arc->vm); | ||
|
||
/* | ||
* Advance the async state machine. | ||
|
@@ -192,15 +199,14 @@ | |
/* | ||
* Do the actual revocation pass. | ||
*/ | ||
error = vm_cheri_revoke_pass_locked(&arc->cookie); | ||
error = vm_cheri_revoke_pass_locked(arc->vm, &arc->cookie); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks a bit weird to use this after it was seemingly free'd above. It might be clearer to the reader with a comment and a local
|
||
|
||
/* | ||
* A revocation pass is done. Advance the state machine again | ||
* so that the application can see the result. | ||
*/ | ||
vm_cheri_revoke_pass_async_post(map, error); | ||
|
||
vmspace_free(arc->vm); | ||
free(arc, M_REVOKE); | ||
} | ||
|
||
|
@@ -907,10 +913,14 @@ | |
* The map must be read-locked on entry and will be read-locked on exit, but | ||
* the lock may be dropped internally. The map must, therefore, also be | ||
* held across invocation. | ||
* | ||
* The containing vmspace may be referenced by the "vm" parameter to signal that | ||
* the revocation sweep is asynchronous and should terminate if the caller ends | ||
* up holding the final vmspace reference. | ||
*/ | ||
static int | ||
vm_cheri_revoke_map_entry(const struct vm_cheri_revoke_cookie *crc, | ||
vm_map_entry_t entry, vm_offset_t *addr) | ||
struct vmspace *vm, vm_map_entry_t entry, vm_offset_t *addr) | ||
{ | ||
vm_offset_t ooffset; | ||
vm_object_t obj; | ||
|
@@ -961,6 +971,13 @@ | |
vm_offset_t oaddr = *addr; | ||
#endif | ||
|
||
/* Has the target process already exited? */ | ||
if (vm != NULL && refcount_load(&vm->vm_refcnt) == 1) { | ||
VM_OBJECT_WUNLOCK(obj); | ||
counter_u64_add(cheri_last_ref_early_finish, 1); | ||
return (KERN_NOT_RECEIVER); | ||
} | ||
|
||
/* Find ourselves in this object */ | ||
ooffset = *addr - entry->start + entry->offset; | ||
|
||
|
@@ -1033,7 +1050,8 @@ | |
* returning. | ||
*/ | ||
static int | ||
vm_cheri_revoke_pass_locked(const struct vm_cheri_revoke_cookie *crc) | ||
vm_cheri_revoke_pass_locked(struct vmspace *vm, | ||
const struct vm_cheri_revoke_cookie *crc) | ||
{ | ||
int res = KERN_SUCCESS; | ||
const vm_map_t map = crc->map; | ||
|
@@ -1056,13 +1074,21 @@ | |
* XXX Somewhere around here we should be resetting | ||
* MPROT_QUARANTINE'd map entries to be usable again, yes? | ||
*/ | ||
res = vm_cheri_revoke_map_entry(crc, entry, &addr); | ||
res = vm_cheri_revoke_map_entry(crc, vm, entry, &addr); | ||
|
||
/* | ||
* We might be bailing out because a page fault failed for | ||
* catastrophic reasons (or polite ones like ptrace()). | ||
*/ | ||
if (res != KERN_SUCCESS) { | ||
switch (res) { | ||
case KERN_SUCCESS: | ||
break; | ||
case KERN_NOT_RECEIVER: | ||
/* The vmspace is orphaned, there is nothing to do. */ | ||
res = KERN_SUCCESS; | ||
goto out; | ||
default: | ||
/* | ||
* We might be bailing out because a page fault failed | ||
* for catastrophic reasons (or polite ones like | ||
* ptrace()). | ||
*/ | ||
printf("CHERI revoke bail va=%lx res=%d\n", addr, res); | ||
goto out; | ||
} | ||
|
@@ -1106,10 +1132,10 @@ | |
int res; | ||
|
||
vm_cheri_revoke_pass_pre(crc->map); | ||
res = vm_cheri_revoke_pass_locked(crc); | ||
res = vm_cheri_revoke_pass_locked(NULL, crc); | ||
vm_cheri_revoke_pass_post(crc->map); | ||
|
||
return (res); | ||
} | ||
|
||
void | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reason to prefer this over the caprevoke stats infrastructure? (Though admittedly I'd not be sad to see the latter get ripped out.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly that I wanted to have a global view of the counter value, and sysctl is more convenient for that. The existing stats infrastructure collects per-process stats and I believe is limited to printing them when the process exits. The right direction might be a hybrid scheme wherein we maintain per-process (really, per-vmspace) and global counters, and use the former to update the latter after each scan.