[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v4][PART 1 2/4] xen/arm: Implement PSCI SYSTEM_SUSPEND call for guests
From: Mykola Kvach <mykola_kvach@xxxxxxxx> This patch adds support for the PSCI SYSTEM_SUSPEND function in the vPSCI (virtual PSCI) interface, allowing guests to request suspend via the PSCI v1.0 SYSTEM_SUSPEND call (both 32-bit and 64-bit variants). The implementation: - Adds SYSTEM_SUSPEND function IDs to PSCI definitions - Implements trapping and handling of SYSTEM_SUSPEND in vPSCI - Allows only non-hardware domains to invoke SYSTEM_SUSPEND; for the hardware domain, PSCI_NOT_SUPPORTED is returned to avoid halting the system in hwdom_shutdown() called from domain_shutdown - Ensures all secondary VCPUs of the calling domain are offline before allowing suspend due to PSCI spec - Treats suspend as a "standby" operation: the domain is shut down with SHUTDOWN_suspend, and resumes execution at the instruction following the call Usage: For Linux-based guests, suspend can be initiated with: echo mem > /sys/power/state or via: systemctl suspend Resuming the guest is performed from control domain using: xl resume <domain> Signed-off-by: Mykola Kvach <mykola_kvach@xxxxxxxx> --- Changes in V3: Dropped all domain flags and related code (which touched common functions like vcpu_unblock), keeping only the necessary changes for Xen suspend/resume, i.e. suspend/resume is now fully supported only for the hardware domain. Proper support for domU suspend/resume will be added in a future patch. This patch does not yet include VCPU context reset or domain context restoration in VCPU. Changes in V4: Dropped all changes related to watchdog, domain is marked as shutting down in domain_shutdown and watchdog timeout handler won't trigger because of it. Previous versions included code to manage Xen watchdog timers during suspend, but this was removed. When a guest OS starts the Xen watchdog (either via the kernel driver or xenwatchdogd), it is responsible for managing that state across suspend/resume. On Linux, the Xen kernel driver properly stops the watchdog during suspend. However, when xenwatchdogd is used instead, suspend handling is incomplete, potentially leading to watchdog-triggered resets on resume. Xen leaves watchdog handling to the guest OS and its services. Dropped all changes related to VCPU context, because instead domain_shutdown is used, so we don't need any extra changes for suspending domain. --- xen/arch/arm/include/asm/perfc_defn.h | 1 + xen/arch/arm/include/asm/psci.h | 2 + xen/arch/arm/vpsci.c | 64 +++++++++++++++++++++++++++ 3 files changed, 67 insertions(+) diff --git a/xen/arch/arm/include/asm/perfc_defn.h b/xen/arch/arm/include/asm/perfc_defn.h index effd25b69e..8dfcac7e3b 100644 --- a/xen/arch/arm/include/asm/perfc_defn.h +++ b/xen/arch/arm/include/asm/perfc_defn.h @@ -33,6 +33,7 @@ PERFCOUNTER(vpsci_system_reset, "vpsci: system_reset") PERFCOUNTER(vpsci_cpu_suspend, "vpsci: cpu_suspend") PERFCOUNTER(vpsci_cpu_affinity_info, "vpsci: cpu_affinity_info") PERFCOUNTER(vpsci_features, "vpsci: features") +PERFCOUNTER(vpsci_system_suspend, "vpsci: system_suspend") PERFCOUNTER(vcpu_kick, "vcpu: notify other vcpu") diff --git a/xen/arch/arm/include/asm/psci.h b/xen/arch/arm/include/asm/psci.h index 4780972621..48a93e6b79 100644 --- a/xen/arch/arm/include/asm/psci.h +++ b/xen/arch/arm/include/asm/psci.h @@ -47,10 +47,12 @@ void call_psci_system_reset(void); #define PSCI_0_2_FN32_SYSTEM_OFF PSCI_0_2_FN32(8) #define PSCI_0_2_FN32_SYSTEM_RESET PSCI_0_2_FN32(9) #define PSCI_1_0_FN32_PSCI_FEATURES PSCI_0_2_FN32(10) +#define PSCI_1_0_FN32_SYSTEM_SUSPEND PSCI_0_2_FN32(14) #define PSCI_0_2_FN64_CPU_SUSPEND PSCI_0_2_FN64(1) #define PSCI_0_2_FN64_CPU_ON PSCI_0_2_FN64(3) #define PSCI_0_2_FN64_AFFINITY_INFO PSCI_0_2_FN64(4) +#define PSCI_1_0_FN64_SYSTEM_SUSPEND PSCI_0_2_FN64(14) /* PSCI v0.2 affinity level state returned by AFFINITY_INFO */ #define PSCI_0_2_AFFINITY_LEVEL_ON 0 diff --git a/xen/arch/arm/vpsci.c b/xen/arch/arm/vpsci.c index d1615be8a6..866bd3128b 100644 --- a/xen/arch/arm/vpsci.c +++ b/xen/arch/arm/vpsci.c @@ -197,6 +197,57 @@ static void do_psci_0_2_system_reset(void) domain_shutdown(d,SHUTDOWN_reboot); } +static int32_t do_psci_1_0_system_suspend(register_t epoint, register_t cid) +{ + struct vcpu *v; + struct domain *d = current->domain; + + /* Drop this check once SYSTEM_SUSPEND is supported in hardware domain */ + if ( is_hardware_domain(d) ) + return PSCI_NOT_SUPPORTED; + + /* Ensure that all CPUs other than the calling one are offline */ + for_each_vcpu ( d, v ) + { + if ( v != current && is_vcpu_online(v) ) + return PSCI_DENIED; + } + + /* + * System suspend requests are treated as performing standby + * as this simplifies Xen implementation. + * + * Arm Power State Coordination Interface (DEN0022F.b) + * + * 5.20.2 Caller responsibilities + * The call is equivalent to using the CPU_SUSPEND call for the deepest + * possible platform powerdown state. Consequently, the caller must observe + * all the rules described for CPU_SUSPEND. See section 5.4. + * + * 5.4.5 Caller responsibilities + * The caller must not assume that a powerdown request will return using + * the specified entry point address. The powerdown request might not + * complete due, for example, to pending interrupts. It is also possible + * that, because of coordination with other cores, the actual state entered + * is shallower than the one requested. Because of this it is possible for + * an implementation to downgrade the powerdown state request to a standby + * state. In the case of a downgrade to standby, the implementation returns + * at the instruction following the PSCI call, at the Exception level of + * the caller, instead of returning by the specified entry point address. + * The return code in this case is SUCCESS. In the case of an early return + * due to a pending wakeup event, the implementation can return at the next + * instruction, with a return code of SUCCESS, or resume at the specified + * entry point address. + * + * 5.4.9 Implementation responsibilities: State on return + * When returning from a standby state, the caller must observe no change in + * core state, other than any timer changes expected because of the time + * spent in the state, and changes in the CPU interface because of the + * wakeup reason. + */ + return domain_shutdown(d, SHUTDOWN_suspend) ? PSCI_DENIED : PSCI_SUCCESS; +} + static int32_t do_psci_1_0_features(uint32_t psci_func_id) { /* /!\ Ordered by function ID and not name */ @@ -214,6 +265,8 @@ static int32_t do_psci_1_0_features(uint32_t psci_func_id) case PSCI_0_2_FN32_SYSTEM_OFF: case PSCI_0_2_FN32_SYSTEM_RESET: case PSCI_1_0_FN32_PSCI_FEATURES: + case PSCI_1_0_FN32_SYSTEM_SUSPEND: + case PSCI_1_0_FN64_SYSTEM_SUSPEND: case ARM_SMCCC_VERSION_FID: return 0; default: @@ -344,6 +397,17 @@ bool do_vpsci_0_2_call(struct cpu_user_regs *regs, uint32_t fid) return true; } + case PSCI_1_0_FN32_SYSTEM_SUSPEND: + case PSCI_1_0_FN64_SYSTEM_SUSPEND: + { + register_t epoint = PSCI_ARG(regs,1); + register_t cid = PSCI_ARG(regs,2); + + perfc_incr(vpsci_system_suspend); + PSCI_SET_RESULT(regs, do_psci_1_0_system_suspend(epoint, cid)); + return true; + } + default: return false; } -- 2.48.1
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |