All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mirela Simonovic <mirela.simonovic@aggios.com>
To: xen-devel@lists.xen.org, xen-devel@lists.xenproject.org
Cc: Stefano Stabellini <sstabellini@kernel.org>,
	dm@aggios.com, saeed.nowshadi@xilinx.com,
	Julien Grall <julien.grall@arm.com>,
	stefano.stabellini@xilinx.com,
	Mirela Simonovic <mirela.simonovic@aggios.com>
Subject: [PATCH 16/18] xen/arm: Save/restore context on suspend/resume
Date: Mon, 12 Nov 2018 12:30:42 +0100	[thread overview]
Message-ID: <1542022244-22977-17-git-send-email-mirela.simonovic@aggios.com> (raw)
In-Reply-To: <1542022244-22977-1-git-send-email-mirela.simonovic@aggios.com>

The context of CPU general purpose and system control registers
has to be saved on suspend and restored on resume. This is
implemented in hyp_suspend and before the return from hyp_resume
function. The hyp_suspend is invoked just before the PSCI system
suspend call is issued to the ATF. The hyp_suspend has to return a
non-zero value so that the calling 'if' statement evaluates to true,
causing the system suspend to be invoked. Upon the resume, context
saved on suspend will be restored, including the link register.
Therefore, after restoring the context the control flow will
return to the address pointed by the saved link register, which
is the place from which the hyp_suspend was called. To ensure
that the calling 'if' statement doesn't again evaluate to true
and initiate system suspend, hyp_resume has to return a zero value
after restoring the context.
Note that the order of saving register context into cpu_context
structure has to match the order of restoring.
Since the suspend/resume is supported only for arm64, we define
a null cpu_context structure so arm32 could compile.

Signed-off-by: Mirela Simonovic <mirela.simonovic@aggios.com>
Signed-off-by: Saeed Nowshadi <saeed.nowshadi@xilinx.com>
---
 xen/arch/arm/arm64/entry.S    | 89 ++++++++++++++++++++++++++++++++++++++++++-
 xen/arch/arm/suspend.c        | 28 ++++++++++++--
 xen/include/asm-arm/suspend.h | 22 +++++++++++
 3 files changed, 135 insertions(+), 4 deletions(-)

diff --git a/xen/arch/arm/arm64/entry.S b/xen/arch/arm/arm64/entry.S
index 5efa30e8ee..861a401b18 100644
--- a/xen/arch/arm/arm64/entry.S
+++ b/xen/arch/arm/arm64/entry.S
@@ -534,6 +534,52 @@ ENTRY(__context_switch)
         mov     sp, x9
         ret
 
+/*
+ * void hyp_suspend(struct cpu_context *ptr)
+ *
+ * x0 - pointer to the storage where callee's context will be saved
+ *
+ * CPU context saved here will be restored on resume in hyp_resume function.
+ * hyp_suspend shall return a non-zero value. Upon restoring context
+ * hyp_resume shall return value zero instead. From C code that invokes
+ * hyp_suspend, the return value is interpreted to determine whether the context
+ * is saved (hyp_suspend) or restored (hyp_resume).
+ */
+ENTRY(hyp_suspend)
+        /* Store callee-saved registers */
+        stp     x19, x20, [x0], #16
+        stp     x21, x22, [x0], #16
+        stp     x23, x24, [x0], #16
+        stp     x25, x26, [x0], #16
+        stp     x27, x28, [x0], #16
+        stp     x29, lr, [x0], #16
+
+        /* Store stack-pointer */
+        mov     x2, sp
+        str     x2, [x0], #8
+
+        /* Store system control registers */
+        mrs     x2, VBAR_EL2
+        str     x2, [x0], #8
+        mrs     x2, VTCR_EL2
+        str     x2, [x0], #8
+        mrs     x2, VTTBR_EL2
+        str     x2, [x0], #8
+        mrs     x2, TPIDR_EL2
+        str     x2, [x0], #8
+        mrs     x2, MDCR_EL2
+        str     x2, [x0], #8
+        mrs     x2, HSTR_EL2
+        str     x2, [x0], #8
+        mrs     x2, CPTR_EL2
+        str     x2, [x0], #8
+        mrs     x2, HCR_EL2
+        str     x2, [x0], #8
+
+        /* hyp_suspend must return a non-zero value */
+        mov     x0, #1
+        ret
+
 ENTRY(hyp_resume)
         msr   DAIFSet, 0xf           /* Disable all interrupts */
 
@@ -622,7 +668,48 @@ mmu_resumed:
         tlbi  alle2
         dsb   sy                     /* Ensure completion of TLB flush */
         isb
-        b .
+
+        /* Now we can access the cpu_context, so restore the context here */
+        ldr     x0, =cpu_context
+
+        /* Restore callee-saved registers */
+        ldp     x19, x20, [x0], #16
+        ldp     x21, x22, [x0], #16
+        ldp     x23, x24, [x0], #16
+        ldp     x25, x26, [x0], #16
+        ldp     x27, x28, [x0], #16
+        ldp     x29, lr, [x0], #16
+
+        /* Restore stack pointer */
+        ldr     x2, [x0], #8
+        mov     sp, x2
+
+        /* Restore system control registers */
+        ldr     x2, [x0], #8
+        msr     VBAR_EL2, x2
+        ldr     x2, [x0], #8
+        msr     VTCR_EL2, x2
+        ldr     x2, [x0], #8
+        msr     VTTBR_EL2, x2
+        ldr     x2, [x0], #8
+        msr     TPIDR_EL2, x2
+        ldr     x2, [x0], #8
+        msr     MDCR_EL2, x2
+        ldr     x2, [x0], #8
+        msr     HSTR_EL2, x2
+        ldr     x2, [x0], #8
+        msr     CPTR_EL2, x2
+        ldr     x2, [x0], #8
+        msr     HCR_EL2, x2
+        isb
+
+        /* Since context is restored return from this function will appear as
+         * return from hyp_suspend. To distinguish a return from hyp_suspend
+         * which is called upon finalizing the suspend, as opposed to return
+         * from this function which executes on resume, we need to return zero
+         * value here. */
+        mov x0, #0
+        ret
 
 /*
  * Local variables:
diff --git a/xen/arch/arm/suspend.c b/xen/arch/arm/suspend.c
index 365c32ec3c..423d9c0e90 100644
--- a/xen/arch/arm/suspend.c
+++ b/xen/arch/arm/suspend.c
@@ -3,6 +3,9 @@
 #include <asm/cpufeature.h>
 #include <asm/event.h>
 #include <asm/psci.h>
+#include <asm/suspend.h>
+
+struct cpu_context cpu_context;
 
 /* Reset values of VCPU architecture specific registers */
 static void vcpu_arch_reset(struct vcpu *v)
@@ -113,6 +116,11 @@ static void vcpu_suspend(register_t epoint, register_t cid)
     _arch_set_info_guest(v, &ctxt);
 }
 
+#ifndef CONFIG_ARM_64
+/* not supported on ARM_32 */
+int32_t hyp_suspend(struct cpu_context *ptr) { return 1; }
+#endif
+
 /* Xen suspend. Note: data is not used (suspend is the suspend to RAM) */
 static long system_suspend(void *data)
 {
@@ -141,9 +149,23 @@ static long system_suspend(void *data)
         goto resume_irqs;
     }
 
-    status = call_psci_system_suspend();
-    if ( status )
-        dprintk(XENLOG_ERR, "PSCI system suspend failed, err=%d\n", status);
+    if ( hyp_suspend(&cpu_context) )
+    {
+        status = call_psci_system_suspend();
+        /*
+         * If suspend is finalized properly by above system suspend PSCI call,
+         * the code below in this 'if' branch will never execute. Execution
+         * will continue from hyp_resume which is the hypervisor's resume point.
+         * In hyp_resume CPU context will be restored and since link-register is
+         * restored as well, it will appear to return from hyp_suspend. The
+         * difference in returning from hyp_suspend on system suspend versus
+         * resume is in function's return value: on suspend, the return value is
+         * a non-zero value, on resume it is zero. That is why the control flow
+         * will not re-enter this 'if' branch on resume.
+         */
+        if ( status )
+            dprintk(XENLOG_ERR, "PSCI system suspend failed, err=%d\n", status);
+    }
 
     system_state = SYS_STATE_resume;
 
diff --git a/xen/include/asm-arm/suspend.h b/xen/include/asm-arm/suspend.h
index 7604e2e2e2..a39071566a 100644
--- a/xen/include/asm-arm/suspend.h
+++ b/xen/include/asm-arm/suspend.h
@@ -1,8 +1,30 @@
 #ifndef __ASM_ARM_SUSPEND_H__
 #define __ASM_ARM_SUSPEND_H__
 
+#ifdef CONFIG_ARM_64
+struct cpu_context {
+    uint64_t callee_regs[12];
+    uint64_t sp;
+    uint64_t vbar_el2;
+    uint64_t vtcr_el2;
+    uint64_t vttbr_el2;
+    uint64_t tpidr_el2;
+    uint64_t mdcr_el2;
+    uint64_t hstr_el2;
+    uint64_t cptr_el2;
+    uint64_t hcr_el2;
+} __aligned(16);
+#else
+struct cpu_context {
+    uint8_t pad;
+};
+#endif
+
+extern struct cpu_context cpu_context;
+
 int32_t domain_suspend(register_t epoint, register_t cid);
 void hyp_resume(void);
+int32_t hyp_suspend(struct cpu_context *ptr);
 
 #endif
 
-- 
2.13.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

  parent reply	other threads:[~2018-11-12 11:31 UTC|newest]

Thread overview: 153+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-11-12 11:30 [PATCH 00/18] xen/arm64: Suspend to RAM support for Xen Mirela Simonovic
2018-11-12 11:30 ` [PATCH 01/18] xen/arm: Move code that initializes VCPU context into a separate function Mirela Simonovic
2018-11-12 11:41   ` Jan Beulich
2018-11-12 11:43   ` Wei Liu
2018-11-12 13:15   ` Julien Grall
2018-11-14 11:45     ` Mirela Simonovic
2018-11-12 11:30 ` [PATCH 02/18] xen/arm: Implement PSCI system suspend call (virtual interface) Mirela Simonovic
2018-11-12 11:42   ` Jan Beulich
2018-11-12 11:50     ` Mirela Simonovic
2018-11-12 12:45       ` Jan Beulich
2018-11-12 15:27   ` Julien Grall
2018-11-12 16:35     ` Mirela Simonovic
2018-11-12 16:41       ` Andrew Cooper
2018-11-12 19:56         ` Julien Grall
2018-11-13  8:32           ` Andrew Cooper
2018-11-14 12:08             ` Mirela Simonovic
2018-11-14 12:49               ` Julien Grall
2018-11-15  0:47                 ` Andrew Cooper
2018-11-15 10:13                   ` Julien Grall
2018-11-15 10:26                     ` Andrew Cooper
2018-11-15 10:33                       ` Mirela Simonovic
2018-11-15 10:59                         ` Julien Grall
2018-11-15 11:10                           ` Mirela Simonovic
2018-11-15 11:38                             ` Julien Grall
2018-11-15 11:42                               ` Mirela Simonovic
2018-11-15 19:30                                 ` Stefano Stabellini
2018-11-15 20:25                                 ` Julien Grall
2018-11-16 22:10                               ` Dario Faggioli
2018-11-15 10:36                       ` Julien Grall
2018-11-15 10:36                       ` Julien Grall
2018-11-15 10:50                         ` Andrew Cooper
2018-11-13  1:53         ` Stefano Stabellini
2018-11-13  9:41           ` Julien Grall
2018-11-13 20:39             ` Stefano Stabellini
2018-11-14 13:10               ` Julien Grall
2018-11-14 23:08                 ` Stefano Stabellini
2018-11-12 20:29       ` Julien Grall
2018-11-13 20:39         ` Stefano Stabellini
2018-11-14 10:45           ` Julien Grall
2018-11-14 12:35             ` Mirela Simonovic
2018-11-14 13:05               ` Julien Grall
2018-11-14 14:48                 ` Julien Grall
2018-11-14 15:36                   ` Mirela Simonovic
2018-11-14 15:37                     ` Mirela Simonovic
2018-11-14 15:51                     ` Julien Grall
2018-11-13 10:23   ` Julien Grall
2018-11-13 15:09     ` Julien Grall
2018-11-14 12:44       ` Mirela Simonovic
2018-11-12 11:30 ` [PATCH 03/18] xen/arm: Save GIC and virtual timer context when the domain suspends Mirela Simonovic
2018-11-12 15:36   ` Julien Grall
2018-11-12 16:52     ` Mirela Simonovic
2018-11-12 17:00       ` Julien Grall
2018-11-12 17:42         ` Mirela Simonovic
2018-11-12 19:20           ` Julien Grall
2018-11-13 20:44             ` Stefano Stabellini
2018-11-14 10:48               ` Julien Grall
2018-11-14 22:45                 ` Stefano Stabellini
2018-11-14 23:39                   ` Julien Grall
2018-11-15  0:05                     ` Julien Grall
2018-11-15  0:35                     ` Stefano Stabellini
2018-11-15 20:29                       ` Julien Grall
2018-11-12 11:30 ` [PATCH 04/18] xen/arm: While a domain is suspended put its watchdogs on pause Mirela Simonovic
2018-11-12 11:47   ` Jan Beulich
2018-11-12 15:17     ` Mirela Simonovic
2018-11-12 15:23       ` Jan Beulich
2018-11-12 15:31         ` Mirela Simonovic
2018-11-12 15:33           ` Andrew Cooper
2018-11-16 22:40             ` Dario Faggioli
2018-11-12 11:30 ` [PATCH 05/18] xen/arm: Trigger Xen suspend when Dom0 completes suspend Mirela Simonovic
2018-11-12 15:45   ` Julien Grall
2018-11-12 23:46     ` Stefano Stabellini
2018-11-13  9:43       ` Julien Grall
2018-11-13 11:26         ` Mirela Simonovic
2018-11-13 11:42           ` Julien Grall
2018-11-14 15:07   ` Julien Grall
2018-11-14 15:40     ` Mirela Simonovic
2018-11-14 17:10       ` Julien Grall
2018-11-14 17:35         ` Mirela Simonovic
2018-11-14 18:48           ` Julien Grall
2018-11-15 12:37             ` Mirela Simonovic
2018-11-15 18:23   ` Julien Grall
2018-11-15 19:17     ` Mirela Simonovic
2018-11-15 20:47       ` Julien Grall
2018-11-12 11:30 ` [PATCH 06/18] xen/x86: Move freeze/thaw_domains into common files Mirela Simonovic
2018-11-13 22:37   ` Stefano Stabellini
2018-11-12 11:30 ` [PATCH 07/18] xen/arm: Freeze domains on suspend and thaw them on resume Mirela Simonovic
2018-11-12 11:30 ` [PATCH 08/18] xen/arm: Disable/enable non-boot physical CPUs on suspend/resume Mirela Simonovic
2018-11-13 22:35   ` Stefano Stabellini
2018-11-14 12:07     ` Julien Grall
2018-11-14 10:52   ` Julien Grall
2018-11-14 13:00     ` Mirela Simonovic
2018-11-14 13:18       ` Julien Grall
2018-11-14 23:04         ` Stefano Stabellini
2018-11-14 23:45           ` Julien Grall
2018-11-15 18:57             ` Stefano Stabellini
2018-11-15 21:09               ` Julien Grall
2018-11-12 11:30 ` [PATCH 09/18] xen/arm: Add rcu_barrier() before enabling non-boot CPUs on resume Mirela Simonovic
2018-11-13 22:42   ` Stefano Stabellini
2018-11-14 12:11   ` Julien Grall
2018-11-14 22:29     ` Stefano Stabellini
2018-11-12 11:30 ` [PATCH 10/18] xen/arm: Implement GIC suspend/resume functions (gicv2 only) Mirela Simonovic
2018-11-13 23:41   ` Stefano Stabellini
2018-11-14  9:13     ` Julien Grall
2018-11-14 11:57       ` Mirela Simonovic
2018-11-14 12:41   ` Julien Grall
2018-11-14 12:52     ` Mirela Simonovic
2018-11-14 13:24       ` Julien Grall
2018-11-14 22:18         ` Stefano Stabellini
2018-11-14 23:50           ` Julien Grall
2018-11-15 18:26             ` Stefano Stabellini
2018-11-12 11:30 ` [PATCH 11/18] xen/arm: Suspend/resume GIC on system suspend/resume Mirela Simonovic
2018-11-12 11:30 ` [PATCH 12/18] xen/arm: Suspend/resume timer interrupt generation Mirela Simonovic
2018-11-12 11:30 ` [PATCH 13/18] xen/arm: Implement PSCI SYSTEM_SUSPEND call (physical interface) Mirela Simonovic
2018-11-14  0:14   ` Stefano Stabellini
2018-11-14 12:03     ` Mirela Simonovic
2018-11-15 21:20   ` Julien Grall
2018-11-12 11:30 ` [PATCH 14/18] xen/arm: Convert setting MMU page tables code into a routine Mirela Simonovic
2018-11-12 11:30 ` [PATCH 15/18] xen/arm: Resume memory management on Xen resume Mirela Simonovic
2018-11-12 16:17   ` Julien Grall
2018-11-13  1:36     ` Stefano Stabellini
2018-11-13  9:59       ` Julien Grall
2018-11-13 21:35         ` Stefano Stabellini
2018-11-13 22:24           ` Julien Grall
2018-11-12 11:30 ` Mirela Simonovic [this message]
2018-11-12 11:30 ` [PATCH 17/18] xen/arm: Resume Dom0 after Xen resumes Mirela Simonovic
2018-11-15 20:31   ` Julien Grall
2018-11-16 10:33     ` Mirela Simonovic
2018-11-16 11:29       ` Mirela Simonovic
2018-11-16 11:44         ` Julien Grall
2018-11-16 12:34           ` Mirela Simonovic
2018-11-16 13:24             ` Julien Grall
2018-11-16 19:03               ` Stefano Stabellini
2018-11-16 19:09                 ` Stefano Stabellini
2018-11-16 21:41                   ` Mirela Simonovic
2018-11-16 21:58                     ` Julien Grall
2018-11-16 23:01                       ` Dario Faggioli
2018-11-16 23:06                         ` Stefano Stabellini
2018-11-17 16:01                           ` Mirela Simonovic
2018-11-17 16:02                             ` Mirela Simonovic
2018-11-17 16:19                               ` Mirela Simonovic
2018-11-27 18:36                             ` Julien Grall
2018-11-29 14:02                               ` Mirela Simonovic
2018-12-04 18:15                                 ` Julien Grall
2018-11-12 11:30 ` [PATCH 18/18] xen/arm: Suspend/resume console on Xen suspend/resume Mirela Simonovic
2018-11-27 18:46   ` Julien Grall
2018-11-12 11:37 ` [PATCH 00/18] xen/arm64: Suspend to RAM support for Xen Mirela Simonovic
2018-11-12 11:49 ` Julien Grall
2018-11-12 12:01   ` Mirela Simonovic
2018-11-12 12:08     ` Julien Grall
2018-11-12 12:35       ` Mirela Simonovic
2018-11-13  2:22   ` Stefano Stabellini
2018-11-13 10:02     ` Julien Grall
2018-11-13 18:06       ` Stefano Stabellini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1542022244-22977-17-git-send-email-mirela.simonovic@aggios.com \
    --to=mirela.simonovic@aggios.com \
    --cc=dm@aggios.com \
    --cc=julien.grall@arm.com \
    --cc=saeed.nowshadi@xilinx.com \
    --cc=sstabellini@kernel.org \
    --cc=stefano.stabellini@xilinx.com \
    --cc=xen-devel@lists.xen.org \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.