[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Minios-devel] [UNIKRAFT PATCH 10/23] plat/xen: Paravirtualization context - Save interrupted thread stack in PDA
The event handling logic, which was ported from Mini-OS, has a critical region before returning to user which can be also interrupted because it is executed after enabling events again. The original fix used a per-cpu data area (PDA) which included a counter for keeping the interrupt nesting level and the interrupt stack address (more details in 'entry64.S'). We extend the PDA to also include the interrupted thread stack address because this can be replaced with the next scheduled thread stack if the previous one was preempted. Signed-off-by: Costin Lupu <costin.lupu@xxxxxxxxx> --- plat/xen/x86/arch_events.c | 9 ++---- plat/xen/x86/entry64.S | 26 +++++++++++++++-- plat/xen/x86/pda.h | 57 ++++++++++++++++++++++++++++++++++++++ plat/xen/x86/pv_ctx.c | 5 ++++ 4 files changed, 88 insertions(+), 9 deletions(-) create mode 100644 plat/xen/x86/pda.h diff --git a/plat/xen/x86/arch_events.c b/plat/xen/x86/arch_events.c index 7d7289fc..379039ab 100644 --- a/plat/xen/x86/arch_events.c +++ b/plat/xen/x86/arch_events.c @@ -31,14 +31,12 @@ #include <x86/cpu.h> #include <uk/plat/config.h> #include <uk/essentials.h> +#include "pda.h" #if defined(__x86_64__) char irqstack[STACK_SIZE] __align(STACK_SIZE); -static struct pda { - int irqcount; /* offset 0 (used in x86_64.S) */ - char *irqstackptr; /* 8 */ -} cpu0_pda; +struct pda cpu0_pda; #endif void arch_init_events(void) @@ -48,8 +46,7 @@ void arch_init_events(void) /* 0xc0000101 is MSR_GS_BASE */ wrmsrl(0xc0000101, (uint64_t) &cpu0_pda); cpu0_pda.irqcount = -1; - cpu0_pda.irqstackptr = - (void *) ((unsigned long) irqstack + STACK_SIZE); + cpu0_pda.irqstackptr = ((unsigned long) irqstack + STACK_SIZE); #endif } diff --git a/plat/xen/x86/entry64.S b/plat/xen/x86/entry64.S index 1aba52c1..0df593e5 100644 --- a/plat/xen/x86/entry64.S +++ b/plat/xen/x86/entry64.S @@ -30,6 +30,10 @@ #include <uk/config.h> #include <xen/xen.h> #include <xen/elfnote.h> +#if CONFIG_HAVE_SCHED_PREEMPT +#include <xen-x86/pv_ctx.h> +#endif /* CONFIG_HAVE_SCHED_PREEMPT */ +#include "pda.h" #define ELFNOTE(name, type, desc) \ .pushsection .note.name ; \ @@ -274,13 +278,18 @@ hypervisor_callback2: cmpq $ecrit,%rax jb critical_region_fixup -11: movq %gs:8, %rax # load IRQ stack - incl %gs:0 # increment nested IRQ counter +11: movq %gs:OFFSETOF_PDA_IRQSTACKPTR, %rax # load IRQ stack + incl %gs:OFFSETOF_PDA_IRQCOUNT # increment nested IRQ counter +#if CONFIG_HAVE_SCHED_PREEMPT + jnz 14f # skip saving interrupted sp + movq %rsp, %gs:OFFSETOF_PDA_USERSTACKPTR # save interrupted thread sp +14: +#endif /* CONFIG_HAVE_SCHED_PREEMPT */ cmovzq %rax, %rsp # if not nested IRQ, then set IRQ sp pushq %rdi # save last sp call do_hypervisor_callback # handle IRQ/event popq %rsp # restore last sp - decl %gs:0 # decrement nested IRQ counter + decl %gs:OFFSETOF_PDA_IRQCOUNT # decrement nested IRQ counter error_exit: movl OFFSETOF_REGS_EFLAGS(%rsp), %eax @@ -290,10 +299,21 @@ error_exit: andb $1, %al # EAX[0] == IRET_RFLAGS.IF & event_mask jnz restore_all_enable_events # != 0 => enable event delivery +#if CONFIG_HAVE_SCHED_PREEMPT + movq %gs:OFFSETOF_PDA_USERSTACKPTR, %rsp # restore interrupted thread sp +#endif /* CONFIG_HAVE_SCHED_PREEMPT */ RESTORE_ALL HYPERVISOR_IRET restore_all_enable_events: +#if CONFIG_HAVE_SCHED_PREEMPT + /* should we restore thread sp? */ + movq %gs:OFFSETOF_PDA_IRQCOUNT, %rax # read IRQ counter + cmpl $-1, %eax # last nested IRQ? + jne 17f # skip restoring interrupted sp + movq %gs:OFFSETOF_PDA_USERSTACKPTR, %rsp # restore interrupted thread sp +17: +#endif /* CONFIG_HAVE_SCHED_PREEMPT */ RESTORE_ALL pushq %rax # save rax; it will be clobbered later RSP_OFFSET=8 # record the stack frame layout changes diff --git a/plat/xen/x86/pda.h b/plat/xen/x86/pda.h new file mode 100644 index 00000000..3060411e --- /dev/null +++ b/plat/xen/x86/pda.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Authors: Costin Lupu <costin.lupu@xxxxxxxxx> + * + * Copyright (c) 2019, University Politehnica of Bucharest. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY. + */ + +#ifndef PLAT_XEN_X86_PDA_H_ +#define PLAT_XEN_X86_PDA_H_ + +#include <uk/config.h> + +#ifndef __ASSEMBLY__ +struct pda { + int irqcount; /* offset 0 (used in entry64.S) */ + __uptr irqstackptr; /* 8 */ +#if CONFIG_HAVE_SCHED_PREEMPT + __uptr userstackptr; /* 16 */ +#endif +}; + +extern struct pda cpu0_pda; + +#endif /* __ASSEMBLY__ */ + +#define OFFSETOF_PDA_IRQCOUNT 0 +#define OFFSETOF_PDA_IRQSTACKPTR 8 +#define OFFSETOF_PDA_USERSTACKPTR 16 + +#endif /* PLAT_XEN_X86_PDA_H_ */ diff --git a/plat/xen/x86/pv_ctx.c b/plat/xen/x86/pv_ctx.c index a354621e..f3f1a79b 100644 --- a/plat/xen/x86/pv_ctx.c +++ b/plat/xen/x86/pv_ctx.c @@ -40,6 +40,7 @@ #include <x86/cpu_defs.h> #include <xen-x86/traps.h> #include <xen-x86/pv_ctx.h> +#include "pda.h" static void pv_ctx_init(void *ctx, unsigned long sp); @@ -89,6 +90,10 @@ static void pv_ctx_switch(void *prevctx, void *nextctx) /* switching interrupted to interrupted */ next_hw_ctx->interrupted = false; + /* switch interrupted stack in PDA */ + prev_hw_ctx->sw_ctx.sp = cpu0_pda.userstackptr; + cpu0_pda.userstackptr = next_hw_ctx->sw_ctx.sp; + } else { /* yielding */ if (next_hw_ctx->interrupted) { -- 2.20.1 _______________________________________________ Minios-devel mailing list Minios-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/minios-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |