[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


  • To: minios-devel@xxxxxxxxxxxxx
  • From: Costin Lupu <costin.lupu@xxxxxxxxx>
  • Date: Mon, 8 Jul 2019 11:33:39 +0300
  • Cc: felipe.huici@xxxxxxxxx, simon.kuenzer@xxxxxxxxx
  • Delivery-date: Mon, 08 Jul 2019 08:50:19 +0000
  • Ironport-phdr: 9a23:j6o0nhB8hDLNeuUaLMwhUyQJP3N1i/DPJgcQr6AfoPdwSPX6pMbcNUDSrc9gkEXOFd2Cra4d0ayK6+u4BSQp2tWoiDg6aptCVhsI2409vjcLJ4q7M3D9N+PgdCcgHc5PBxdP9nC/NlVJSo6lPwWB6nK94iQPFRrhKAF7Ovr6GpLIj8Swyuu+54Dfbx9HiTagf79+Nhq7oRneusUKjoZpN7o8xAbOrnZUYepd2HlmJUiUnxby58ew+IBs/iFNsP8/9MBOTLv3cb0gQbNXEDopPWY15Nb2tRbYVguA+mEcUmQNnRVWBQXO8Qz3UY3wsiv+sep9xTWaMMjrRr06RTiu86FmQwLuhSwaNTA27XvXh9RwgqxFvRyvqR9xzYnWb4GbL/dyYr/RcMkGSWdbQspdSypMCZ68YYsVCOoBOP5Vopf6p1sVsRu+BA+sD/7pxD9Vnn/2wLAx3uM9HgHBxwwgA9MOsHLOoNXxKacSSf21wbLUwjXYdf9WwSr955PSfhA7pvGBRLR9etffx0koEgPKlFSQqYr9MjyL0OQNr3Kb7uphWO+gkWInsBp+rz6yzckvkonEnp8Zx1/Z+Sljw4s4Jce0RFBlbdOmCpdduTmWO5Z5T88/WW1luyY3xqcYtZO1ciUG0okryhHBZ/GBboOG+AjsVPyLLjd9nH9lfbW/iAus/kW40e38U9W00E5NripYjtnArnAN2ALX6siAUvZ94EKh1iyO1wDX8O1LPVs0mbDDK5482bE8jIATsUPbEi/3nkX5krOWe1059uWn9ujreLbrq5+GO4NqlA3zML4il8KnDeQ9KAcOXmyb+eqm1L3k+E30WKlFjvotkqnFsZDaI94XpqqkAw9Nz4Yu8AqwDyy83NQAgHkIN0hJeAiAj4TxIVHBPOj4Deujg1SriDprwvHGPrvgApXKNXjPiarucqhj60FCzAo+1tRf55NPCrEdO/L/QEDwu8LeDhMjNAy02ennAs1n1owCQWKPHrOZMKTKvF+G+O0vJ+iMZJcLtzrnK/gl+v/ugmM4mVIGe6mmw4cYaHSiEft9OUmWf2fsiM8bEWgWpgo+UPDqiFqaXD5IZnayWqU85jchBIKlEIfMWIatgb2f0yehBZBWYH5JBUyIEXjybIqIQekDaD/BavNmxzkFU7mmUMot2A+jsCf+yqF7NazE9ytesojsh/Zv4OiGvhYp6T1yR+CAy3zFG2pzhX8JQXkywbhiiUdmjE+e2+5ihKoLRpRo+/pVX1JiZtbnxOtgBoWqVw==
  • Ironport-sdr: Xhz1BBE19Lp2YR0V59ZxQbAvQl78xZIvbZKL6y2Hr6qOJLClZfRlrHRM8L5sUn+SfJB7TxyBAa BJssiiDmx4rA==
  • List-id: Mini-os development list <minios-devel.lists.xenproject.org>

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

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.