systrap: handler interrupted contexts in __export_start

contexts with pending interrupts should not be executed.

PiperOrigin-RevId: 521835904
This commit is contained in:
Andrei Vagin
2023-04-04 12:36:37 -07:00
committed by gVisor bot
parent 8820b3bb90
commit 5645cdf2d4
3 changed files with 44 additions and 36 deletions
@@ -160,6 +160,7 @@ static void set_fsbase(uint64_t fsbase) {
struct thread_context *switch_context_amd64(
struct sysmsg *sysmsg, struct thread_context *ctx,
enum thread_state new_thread_state, enum context_state new_context_state) {
struct thread_context *old_ctx = sysmsg->context;
for (;;) {
// TODO(b/271631387): Once stub code globals can be used between objects
@@ -189,6 +190,9 @@ struct thread_context *switch_context_amd64(
break;
}
}
if (old_ctx != ctx || ctx->last_thread_id != sysmsg->thread_id) {
ctx->fpstate_changed = 1;
}
return ctx;
}
@@ -366,6 +370,20 @@ void __syshandler() {
}
}
void __export_start(struct sysmsg *sysmsg, void *_ucontext) {
#if defined(__x86_64__)
asm volatile("movq %%gs:0, %0\n" : "=r"(sysmsg) : :);
if (sysmsg->self != sysmsg) {
panic(0xdeaddead);
}
#endif
struct thread_context *ctx = switch_context_amd64(
sysmsg, NULL, THREAD_STATE_EVENT, CONTEXT_STATE_INVALID);
restore_state(sysmsg, ctx, _ucontext);
}
// asm_restore_state is implemented in syshandler_amd64.S
void asm_restore_state();
@@ -91,6 +91,10 @@ static void ptregs_to_gregs(ucontext_t *ucontext,
ucontext->uc_mcontext.pstate = ptregs->pstate;
}
void __export_start(struct sysmsg *sysmsg, void *_ucontext) {
panic(0x11111111);
}
void __export_sighandler(int signo, siginfo_t *siginfo, void *_ucontext) {
ucontext_t *ucontext = _ucontext;
void *sp = sysmsg_sp();
@@ -98,16 +102,18 @@ void __export_sighandler(int signo, siginfo_t *siginfo, void *_ucontext) {
if (sysmsg != sysmsg->self) panic(0xdeaddead);
int32_t thread_state = __atomic_load_n(&sysmsg->state, __ATOMIC_ACQUIRE);
uint32_t ctx_state = CONTEXT_STATE_INVALID;
struct thread_context *ctx = NULL, *old_ctx = NULL;
if (__export_context_decoupling_exp &&
thread_state == THREAD_STATE_INITIALIZING) {
// Find a new context and exit to restore it.
__export_start(sysmsg, _ucontext);
return;
goto init;
}
struct thread_context *ctx = sysmsg->context;
ctx = sysmsg->context;
old_ctx = sysmsg->context;
uint32_t ctx_state = CONTEXT_STATE_INVALID;
ctx->signo = signo;
gregs_to_ptregs(ucontext, &ctx->ptregs);
@@ -154,6 +160,7 @@ void __export_sighandler(int signo, siginfo_t *siginfo, void *_ucontext) {
return;
}
init:
for (;;) {
if (__export_context_decoupling_exp) {
ctx = switch_context(sysmsg, ctx, ctx_state);
@@ -174,6 +181,10 @@ void __export_sighandler(int signo, siginfo_t *siginfo, void *_ucontext) {
break;
}
}
if (old_ctx != ctx || ctx->last_thread_id != sysmsg->thread_id) {
ctx->fpstate_changed = 1;
}
restore_state(sysmsg, ctx, _ucontext);
}
+11 -32
View File
@@ -259,41 +259,20 @@ struct thread_context *switch_context(struct sysmsg *sysmsg,
enum context_state new_context_state) {
struct context_queue *queue = __export_context_queue_addr;
__atomic_sub_fetch(&queue->num_active_contexts, 1, __ATOMIC_ACQ_REL);
__atomic_store_n(&ctx->thread_id, INVALID_THREAD_ID, __ATOMIC_RELEASE);
__atomic_store_n(&ctx->last_thread_id, sysmsg->thread_id, __ATOMIC_RELEASE);
__atomic_store_n(&ctx->state, new_context_state, __ATOMIC_RELEASE);
if (__atomic_load_n(&ctx->sentry_fast_path, __ATOMIC_ACQUIRE) == 0) {
int ret = sys_futex(&ctx->state, FUTEX_WAKE, 1, NULL, NULL, 0);
if (ret < 0) {
panic(ret);
if (ctx) {
__atomic_sub_fetch(&queue->num_active_contexts, 1, __ATOMIC_ACQ_REL);
__atomic_store_n(&ctx->thread_id, INVALID_THREAD_ID, __ATOMIC_RELEASE);
__atomic_store_n(&ctx->last_thread_id, sysmsg->thread_id, __ATOMIC_RELEASE);
__atomic_store_n(&ctx->state, new_context_state, __ATOMIC_RELEASE);
if (__atomic_load_n(&ctx->sentry_fast_path, __ATOMIC_ACQUIRE) == 0) {
int ret = sys_futex(&ctx->state, FUTEX_WAKE, 1, NULL, NULL, 0);
if (ret < 0) {
panic(ret);
}
}
}
struct thread_context *old_ctx = sysmsg->context;
ctx = get_context(sysmsg);
if (old_ctx != ctx || ctx->last_thread_id != sysmsg->thread_id) {
ctx->fpstate_changed = 1;
}
return ctx;
}
void __export_start(struct sysmsg *sysmsg, void *_ucontext) {
#if defined(__x86_64__)
asm volatile("movq %%gs:0, %0\n" : "=r"(sysmsg) : :);
if (sysmsg->self != sysmsg) {
panic(0xdeaddead);
}
#endif
struct thread_context *ctx = get_context(sysmsg);
__atomic_store_n(&ctx->fpstate_changed, 1, __ATOMIC_RELEASE);
__atomic_store_n(&ctx->thread_id, sysmsg->thread_id, __ATOMIC_RELEASE);
restore_state(sysmsg, ctx, _ucontext);
return get_context(sysmsg);
}
int wait_state(struct sysmsg *sysmsg, enum thread_state new_thread_state) {