Catching faults

5 views
Skip to first unread message

Davide Libenzi

unread,
Oct 15, 2015, 10:13:26 AM10/15/15
to aka...@googlegroups.com
Here is a snapshot (to be cleaned) of the test that is now with the RB tree VMR branch, which shows how to read/write to invalid VMAs and have the function doing this simply exit with an error code.
This is from userspace.
It actually uses simply sigaction, by patching the %rip register of the return-to-userspace context.
This example uses exception tables in the way Linux does copy to/from user memory.

IMHO it would be nice to have such support in Akaros as well.
Code is pretty simple. At boot you load the exception table section, and sort by insn address (so that we can bisect in logN).
During fault handling, we have a function which takes the fault %rip and either returns a fixup %rip, or 0.
If a valid fixup is found, fault code replaces the return-to-userspace %rip with the fixup one.

As far as raw access to Akaros fault reflection into userspace, at this time, from my chats with Kevin, it looks clunky.
This because it involves the user to do quite a bit of setup work in order to be able to use it.
If you simply wants the ability to catch a fault, it seems that you have to deal with a lot of other things (events, scheduling, etc...) as well.
It would be nice it that layer would be hidden underneath, and simpler userspace APIs provided, for normal cases.
Then power-users which really wants to dig into the internals, will be able to do it using the more core APIs.
This not only helps in making userspace code easier, but, by avoiding them to cut&paste a lot of setup code in every program, it minimizes the amount of userspace code to be fixed in case of any of the many core APIs involved, changes signature or behaviour.


mmap_stress_test.c

Barret Rhoden

unread,
Oct 15, 2015, 2:11:23 PM10/15/15
to aka...@googlegroups.com
On 2015-10-15 at 07:13 "'Davide Libenzi' via Akaros"
<aka...@googlegroups.com> wrote:
> Here is a snapshot (to be cleaned) of the test that is now with the
> RB tree VMR branch, which shows how to read/write to invalid VMAs and
> have the function doing this simply exit with an error code.
> This is from userspace.
> It actually uses simply sigaction, by patching the %rip register of
> the return-to-userspace context.
> This example uses exception tables in the way Linux does copy to/from
> user memory.
>
> IMHO it would be nice to have such support in Akaros as well.
> Code is pretty simple. At boot you load the exception table section,
> and sort by insn address (so that we can bisect in logN).
> During fault handling, we have a function which takes the fault %rip
> and either returns a fixup %rip, or 0.
> If a valid fixup is found, fault code replaces the
> return-to-userspace %rip with the fixup one.

This part above seems like it'd work with Akaros. It's just a question
of how to change the uthread's context easily.

> As far as raw access to Akaros fault reflection into userspace, at
> this time, from my chats with Kevin, it looks clunky.
> This because it involves the user to do quite a bit of setup work in
> order to be able to use it.
> If you simply wants the ability to catch a fault, it seems that you
> have to deal with a lot of other things (events, scheduling, etc...)
> as well.

I haven't tried it, but I think you can just interpose on the sched ops
table. For instance, the uthread code will just call

sched_ops->thread_refl_fault()

If the user changed that func pointer to their own, then it could
adjust the context before it got started. Something like:

old_2ls_op = sched_ops->thread_refl_fault();
sched_ops = my_handler();

void my_handler(args) {
if a magic RIP
adjust uthread->ctx
return
old_2ls_op(args)
}

So that the user handler gets "first dibs" on it.

> It would be nice it that layer would be hidden underneath, and
> simpler userspace APIs provided, for normal cases.

I agree that even my example could use a smoother interface. Part of
it is that the interposing function has limited functionality. All it
can do is muck with the context and return (meaning, start the thread),
or call the old 2LS op. It can't stop the thread or do anything
related to scheduling. For instance, pth_thread_refl_fault() does some
bookkeeping to trace uthread as not running - that's the sort of thing
the user's handler shouldn't muck with.

But if all we want to support is "given trap Foo, you can muck with the
context and let it run", then we're not actually too bad at this pont.
Maybe just use a helper function to set and track the old 2LS op, or
have a series of function pointers that can get installed so we can
hook in a bunch of different handlers if that's desired.

Whatever we come up with, I'd like it to be usable for restartable
atomic sequences. The triggering mechanism wouldn't be faults,
exactly, but it's something where we want to do consider doing
something to a uthread's context before it runs again.

Background:
http://dl.acm.org/citation.cfm?id=143523
And more recently:
https://lwn.net/Articles/650333/
(But we can do it without kernel support.)


Barret

Davide Libenzi

unread,
Oct 15, 2015, 8:53:09 PM10/15/15
to Akaros
Ideally, catching faults in userspace should be as easy as signals, as far as registration goes.




Barret

--
You received this message because you are subscribed to the Google Groups "Akaros" group.
To unsubscribe from this group and stop receiving emails from it, send an email to akaros+un...@googlegroups.com.
To post to this group, send email to aka...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Davide Libenzi

unread,
Oct 15, 2015, 9:00:05 PM10/15/15
to Akaros
Example:

typedef int fault_status_t;

static const fault_status_t status_continue_next_handler = 0;
static const fault_status_t status_fault_fixed = 1;
static const fault_status_t status_fail = 2;

typedef fault_status_t (*fault_handler_t)(struct user_context*);

int register_fault_handler(fault_handler_t handler, bool insert_tail);
int unregister_fault_handler(fault_handler_t handler);


Then the lower level machinery would just have a list of handlers, and cycle through them until according to the status code returned by the previous.


Reply all
Reply to author
Forward
0 new messages