History

Merge branch kvm-arm64/psci-1.3 into kvmarm/next

* kvm-arm64/psci-1.3: : PSCI v1.3 support, courtesy of David Woodhouse : : Bump KVM's PSCI implementation up to v1.3, with the added bonus of : implementing the SYSTEM_OFF2 call. Like other system-scoped PSCI calls, : this gets relayed to userspace for further processing with a new : KVM_SYSTEM_EVENT_SHUTDOWN flag. : : As an added bonus, implement client-side support for hibernation with : the SYSTEM_OFF2 call. arm64: Use SYSTEM_OFF2 PSCI call to power off for hibernate KVM: arm64: nvhe: Pass through PSCI v1.3 SYSTEM_OFF2 call KVM: selftests: Add test for PSCI SYSTEM_OFF2 KVM: arm64: Add support for PSCI v1.2 and v1.3 KVM: arm64: Add PSCI v1.3 SYSTEM_OFF2 function for hibernation firmware/psci: Add definitions for PSCI v1.3 specification

Oliver Upton committed 2 years ago

Commit 7ccd6152 parents 2865463 3e251af10 files · +212 −3Browse files

Unified · Split

10 files
  1. Documentation/virt/kvm/api.rst +10 −0
  2. arch/arm64/include/uapi/asm/kvm.h +6 −0
  3. arch/arm64/kvm/hyp/nvhe/psci-relay.c +2 −0
  4. arch/arm64/kvm/hypercalls.c +2 −0
  5. arch/arm64/kvm/psci.c +43 −1
  6. drivers/firmware/psci/psci.c +45 −0
  7. include/kvm/arm_psci.h +3 −1
  8. include/uapi/linux/psci.h +5 −0
  9. kernel/power/hibernate.c +4 −1
  10. tools/testing/selftests/kvm/aarch64/psci_test.c +92 −0
Documentation/virt/kvm/api.rst+10−0
@@ -6855,6 +6855,10 @@ the first `ndata` items (possibly zero) of the data array are valid. · 6854 unmodified lines
6855 the guest issued a SYSTEM_RESET2 call according to v1.1 of the PSCI6855 the guest issued a SYSTEM_RESET2 call according to v1.1 of the PSCI
6856 specification.6856 specification.
6857 6857
6858 - for arm64, data[0] is set to KVM_SYSTEM_EVENT_SHUTDOWN_FLAG_PSCI_OFF2
6859 if the guest issued a SYSTEM_OFF2 call according to v1.3 of the PSCI
6860 specification.
6861
6858 - for RISC-V, data[0] is set to the value of the second argument of the6862 - for RISC-V, data[0] is set to the value of the second argument of the
6859 ``sbi_system_reset`` call.6863 ``sbi_system_reset`` call.
6860 6864
@@ -6888,6 +6892,12 @@ either: · 27 unmodified lines
6888 - Deny the guest request to suspend the VM. See ARM DEN0022D.b 5.19.26892 - Deny the guest request to suspend the VM. See ARM DEN0022D.b 5.19.2
6889 "Caller responsibilities" for possible return values.6893 "Caller responsibilities" for possible return values.
6890 6894
6895Hibernation using the PSCI SYSTEM_OFF2 call is enabled when PSCI v1.3
6896is enabled. If a guest invokes the PSCI SYSTEM_OFF2 function, KVM will
6897exit to userspace with the KVM_SYSTEM_EVENT_SHUTDOWN event type and with
6898data[0] set to KVM_SYSTEM_EVENT_SHUTDOWN_FLAG_PSCI_OFF2. The only
6899supported hibernate type for the SYSTEM_OFF2 function is HIBERNATE_OFF.
6900
6891::6901::
6892 6902
6893 /* KVM_EXIT_IOAPIC_EOI */6903 /* KVM_EXIT_IOAPIC_EOI */
arch/arm64/include/uapi/asm/kvm.h+6−0
@@ -484,6 +484,12 @@ enum { · 483 unmodified lines
484 */484 */
485#define KVM_SYSTEM_EVENT_RESET_FLAG_PSCI_RESET2 (1ULL << 0)485#define KVM_SYSTEM_EVENT_RESET_FLAG_PSCI_RESET2 (1ULL << 0)
486 486
487/*
488 * Shutdown caused by a PSCI v1.3 SYSTEM_OFF2 call.
489 * Valid only when the system event has a type of KVM_SYSTEM_EVENT_SHUTDOWN.
490 */
491#define KVM_SYSTEM_EVENT_SHUTDOWN_FLAG_PSCI_OFF2 (1ULL << 0)
492
487/* run->fail_entry.hardware_entry_failure_reason codes. */493/* run->fail_entry.hardware_entry_failure_reason codes. */
488#define KVM_EXIT_FAIL_ENTRY_CPU_UNSUPPORTED (1ULL << 0)494#define KVM_EXIT_FAIL_ENTRY_CPU_UNSUPPORTED (1ULL << 0)
489 495
arch/arm64/kvm/hyp/nvhe/psci-relay.c+2−0
@@ -265,6 +265,8 @@ static unsigned long psci_1_0_handler(u64 func_id, struct kvm_cpu_context *host_ · 264 unmodified lines
265 case PSCI_1_0_FN_PSCI_FEATURES:265 case PSCI_1_0_FN_PSCI_FEATURES:
266 case PSCI_1_0_FN_SET_SUSPEND_MODE:266 case PSCI_1_0_FN_SET_SUSPEND_MODE:
267 case PSCI_1_1_FN64_SYSTEM_RESET2:267 case PSCI_1_1_FN64_SYSTEM_RESET2:
268 case PSCI_1_3_FN_SYSTEM_OFF2:
269 case PSCI_1_3_FN64_SYSTEM_OFF2:
268 return psci_forward(host_ctxt);270 return psci_forward(host_ctxt);
269 case PSCI_1_0_FN64_SYSTEM_SUSPEND:271 case PSCI_1_0_FN64_SYSTEM_SUSPEND:
270 return psci_system_suspend(func_id, host_ctxt);272 return psci_system_suspend(func_id, host_ctxt);
arch/arm64/kvm/hypercalls.c+2−0
@@ -575,6 +575,8 @@ int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) · 574 unmodified lines
575 case KVM_ARM_PSCI_0_2:575 case KVM_ARM_PSCI_0_2:
576 case KVM_ARM_PSCI_1_0:576 case KVM_ARM_PSCI_1_0:
577 case KVM_ARM_PSCI_1_1:577 case KVM_ARM_PSCI_1_1:
578 case KVM_ARM_PSCI_1_2:
579 case KVM_ARM_PSCI_1_3:
578 if (!wants_02)580 if (!wants_02)
579 return -EINVAL;581 return -EINVAL;
580 vcpu->kvm->arch.psci_version = val;582 vcpu->kvm->arch.psci_version = val;
arch/arm64/kvm/psci.c+43−1
@@ -194,6 +194,12 @@ static void kvm_psci_system_off(struct kvm_vcpu *vcpu) · 193 unmodified lines
194 kvm_prepare_system_event(vcpu, KVM_SYSTEM_EVENT_SHUTDOWN, 0);194 kvm_prepare_system_event(vcpu, KVM_SYSTEM_EVENT_SHUTDOWN, 0);
195}195}
196 196
197static void kvm_psci_system_off2(struct kvm_vcpu *vcpu)
198{
199 kvm_prepare_system_event(vcpu, KVM_SYSTEM_EVENT_SHUTDOWN,
200 KVM_SYSTEM_EVENT_SHUTDOWN_FLAG_PSCI_OFF2);
201}
202
197static void kvm_psci_system_reset(struct kvm_vcpu *vcpu)203static void kvm_psci_system_reset(struct kvm_vcpu *vcpu)
198{204{
199 kvm_prepare_system_event(vcpu, KVM_SYSTEM_EVENT_RESET, 0);205 kvm_prepare_system_event(vcpu, KVM_SYSTEM_EVENT_RESET, 0);
@@ -322,7 +328,7 @@ static int kvm_psci_1_x_call(struct kvm_vcpu *vcpu, u32 minor) · 122 unmodified lines
322 328
323 switch(psci_fn) {329 switch(psci_fn) {
324 case PSCI_0_2_FN_PSCI_VERSION:330 case PSCI_0_2_FN_PSCI_VERSION:
325 val = minor == 0 ? KVM_ARM_PSCI_1_0 : KVM_ARM_PSCI_1_1;331 val = PSCI_VERSION(1, minor);
326 break;332 break;
327 case PSCI_1_0_FN_PSCI_FEATURES:333 case PSCI_1_0_FN_PSCI_FEATURES:
328 arg = smccc_get_arg1(vcpu);334 arg = smccc_get_arg1(vcpu);
@@ -358,6 +364,11 @@ static int kvm_psci_1_x_call(struct kvm_vcpu *vcpu, u32 minor) · 29 unmodified lines
358 if (minor >= 1)364 if (minor >= 1)
359 val = 0;365 val = 0;
360 break;366 break;
367 case PSCI_1_3_FN_SYSTEM_OFF2:
368 case PSCI_1_3_FN64_SYSTEM_OFF2:
369 if (minor >= 3)
370 val = PSCI_1_3_OFF_TYPE_HIBERNATE_OFF;
371 break;
361 }372 }
362 break;373 break;
363 case PSCI_1_0_FN_SYSTEM_SUSPEND:374 case PSCI_1_0_FN_SYSTEM_SUSPEND:
@@ -392,6 +403,33 @@ static int kvm_psci_1_x_call(struct kvm_vcpu *vcpu, u32 minor) · 28 unmodified lines
392 break;403 break;
393 }404 }
394 break;405 break;
406 case PSCI_1_3_FN_SYSTEM_OFF2:
407 kvm_psci_narrow_to_32bit(vcpu);
408 fallthrough;
409 case PSCI_1_3_FN64_SYSTEM_OFF2:
410 if (minor < 3)
411 break;
412
413 arg = smccc_get_arg1(vcpu);
414 /*
415 * SYSTEM_OFF2 defaults to HIBERNATE_OFF if arg1 is zero. arg2
416 * must be zero.
417 */
418 if ((arg && arg != PSCI_1_3_OFF_TYPE_HIBERNATE_OFF) ||
419 smccc_get_arg2(vcpu) != 0) {
420 val = PSCI_RET_INVALID_PARAMS;
421 break;
422 }
423 kvm_psci_system_off2(vcpu);
424 /*
425 * We shouldn't be going back to the guest after receiving a
426 * SYSTEM_OFF2 request. Preload a return value of
427 * INTERNAL_FAILURE should userspace ignore the exit and resume
428 * the vCPU.
429 */
430 val = PSCI_RET_INTERNAL_FAILURE;
431 ret = 0;
432 break;
395 default:433 default:
396 return kvm_psci_0_2_call(vcpu);434 return kvm_psci_0_2_call(vcpu);
397 }435 }
@@ -449,6 +487,10 @@ int kvm_psci_call(struct kvm_vcpu *vcpu) · 51 unmodified lines
449 }487 }
450 488
451 switch (version) {489 switch (version) {
490 case KVM_ARM_PSCI_1_3:
491 return kvm_psci_1_x_call(vcpu, 3);
492 case KVM_ARM_PSCI_1_2:
493 return kvm_psci_1_x_call(vcpu, 2);
452 case KVM_ARM_PSCI_1_1:494 case KVM_ARM_PSCI_1_1:
453 return kvm_psci_1_x_call(vcpu, 1);495 return kvm_psci_1_x_call(vcpu, 1);
454 case KVM_ARM_PSCI_1_0:496 case KVM_ARM_PSCI_1_0:
drivers/firmware/psci/psci.c+45−0
@@ -78,6 +78,7 @@ struct psci_0_1_function_ids get_psci_0_1_function_ids(void) · 77 unmodified lines
78 78
79static u32 psci_cpu_suspend_feature;79static u32 psci_cpu_suspend_feature;
80static bool psci_system_reset2_supported;80static bool psci_system_reset2_supported;
81static bool psci_system_off2_hibernate_supported;
81 82
82static inline bool psci_has_ext_power_state(void)83static inline bool psci_has_ext_power_state(void)
83{84{
@@ -333,6 +334,36 @@ static void psci_sys_poweroff(void) · 249 unmodified lines
333 invoke_psci_fn(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0);334 invoke_psci_fn(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0);
334}335}
335 336
337#ifdef CONFIG_HIBERNATION
338static int psci_sys_hibernate(struct sys_off_data *data)
339{
340 /*
341 * If no hibernate type is specified SYSTEM_OFF2 defaults to selecting
342 * HIBERNATE_OFF.
343 *
344 * There are hypervisors in the wild that do not align with the spec and
345 * reject calls that explicitly provide a hibernate type. For
346 * compatibility with these nonstandard implementations, pass 0 as the
347 * type.
348 */
349 if (system_entering_hibernation())
350 invoke_psci_fn(PSCI_FN_NATIVE(1_3, SYSTEM_OFF2), 0, 0, 0);
351 return NOTIFY_DONE;
352}
353
354static int __init psci_hibernate_init(void)
355{
356 if (psci_system_off2_hibernate_supported) {
357 /* Higher priority than EFI shutdown, but only for hibernate */
358 register_sys_off_handler(SYS_OFF_MODE_POWER_OFF,
359 SYS_OFF_PRIO_FIRMWARE + 2,
360 psci_sys_hibernate, NULL);
361 }
362 return 0;
363}
364subsys_initcall(psci_hibernate_init);
365#endif
366
336static int psci_features(u32 psci_func_id)367static int psci_features(u32 psci_func_id)
337{368{
338 return invoke_psci_fn(PSCI_1_0_FN_PSCI_FEATURES,369 return invoke_psci_fn(PSCI_1_0_FN_PSCI_FEATURES,
@@ -364,6 +395,7 @@ static const struct { · 25 unmodified lines
364 PSCI_ID_NATIVE(1_1, SYSTEM_RESET2),395 PSCI_ID_NATIVE(1_1, SYSTEM_RESET2),
365 PSCI_ID(1_1, MEM_PROTECT),396 PSCI_ID(1_1, MEM_PROTECT),
366 PSCI_ID_NATIVE(1_1, MEM_PROTECT_CHECK_RANGE),397 PSCI_ID_NATIVE(1_1, MEM_PROTECT_CHECK_RANGE),
398 PSCI_ID_NATIVE(1_3, SYSTEM_OFF2),
367};399};
368 400
369static int psci_debugfs_read(struct seq_file *s, void *data)401static int psci_debugfs_read(struct seq_file *s, void *data)
@@ -525,6 +557,18 @@ static void __init psci_init_system_reset2(void) · 155 unmodified lines
525 psci_system_reset2_supported = true;557 psci_system_reset2_supported = true;
526}558}
527 559
560static void __init psci_init_system_off2(void)
561{
562 int ret;
563
564 ret = psci_features(PSCI_FN_NATIVE(1_3, SYSTEM_OFF2));
565 if (ret < 0)
566 return;
567
568 if (ret & PSCI_1_3_OFF_TYPE_HIBERNATE_OFF)
569 psci_system_off2_hibernate_supported = true;
570}
571
528static void __init psci_init_system_suspend(void)572static void __init psci_init_system_suspend(void)
529{573{
530 int ret;574 int ret;
@@ -655,6 +699,7 @@ static int __init psci_probe(void) · 124 unmodified lines
655 psci_init_cpu_suspend();699 psci_init_cpu_suspend();
656 psci_init_system_suspend();700 psci_init_system_suspend();
657 psci_init_system_reset2();701 psci_init_system_reset2();
702 psci_init_system_off2();
658 kvm_init_hyp_services();703 kvm_init_hyp_services();
659 }704 }
660 705
include/kvm/arm_psci.h+3−1
@@ -14,8 +14,10 @@ · 13 unmodified lines
14#define KVM_ARM_PSCI_0_2 PSCI_VERSION(0, 2)14#define KVM_ARM_PSCI_0_2 PSCI_VERSION(0, 2)
15#define KVM_ARM_PSCI_1_0 PSCI_VERSION(1, 0)15#define KVM_ARM_PSCI_1_0 PSCI_VERSION(1, 0)
16#define KVM_ARM_PSCI_1_1 PSCI_VERSION(1, 1)16#define KVM_ARM_PSCI_1_1 PSCI_VERSION(1, 1)
17#define KVM_ARM_PSCI_1_2 PSCI_VERSION(1, 2)
18#define KVM_ARM_PSCI_1_3 PSCI_VERSION(1, 3)
17 19
18#define KVM_ARM_PSCI_LATEST KVM_ARM_PSCI_1_120#define KVM_ARM_PSCI_LATEST KVM_ARM_PSCI_1_3
19 21
20static inline int kvm_psci_version(struct kvm_vcpu *vcpu)22static inline int kvm_psci_version(struct kvm_vcpu *vcpu)
21{23{
include/uapi/linux/psci.h+5−0
@@ -59,6 +59,7 @@ · 58 unmodified lines
59#define PSCI_1_1_FN_SYSTEM_RESET2 PSCI_0_2_FN(18)59#define PSCI_1_1_FN_SYSTEM_RESET2 PSCI_0_2_FN(18)
60#define PSCI_1_1_FN_MEM_PROTECT PSCI_0_2_FN(19)60#define PSCI_1_1_FN_MEM_PROTECT PSCI_0_2_FN(19)
61#define PSCI_1_1_FN_MEM_PROTECT_CHECK_RANGE PSCI_0_2_FN(20)61#define PSCI_1_1_FN_MEM_PROTECT_CHECK_RANGE PSCI_0_2_FN(20)
62#define PSCI_1_3_FN_SYSTEM_OFF2 PSCI_0_2_FN(21)
62 63
63#define PSCI_1_0_FN64_CPU_DEFAULT_SUSPEND PSCI_0_2_FN64(12)64#define PSCI_1_0_FN64_CPU_DEFAULT_SUSPEND PSCI_0_2_FN64(12)
64#define PSCI_1_0_FN64_NODE_HW_STATE PSCI_0_2_FN64(13)65#define PSCI_1_0_FN64_NODE_HW_STATE PSCI_0_2_FN64(13)
@@ -68,6 +69,7 @@ · 3 unmodified lines
68 69
69#define PSCI_1_1_FN64_SYSTEM_RESET2 PSCI_0_2_FN64(18)70#define PSCI_1_1_FN64_SYSTEM_RESET2 PSCI_0_2_FN64(18)
70#define PSCI_1_1_FN64_MEM_PROTECT_CHECK_RANGE PSCI_0_2_FN64(20)71#define PSCI_1_1_FN64_MEM_PROTECT_CHECK_RANGE PSCI_0_2_FN64(20)
72#define PSCI_1_3_FN64_SYSTEM_OFF2 PSCI_0_2_FN64(21)
71 73
72/* PSCI v0.2 power state encoding for CPU_SUSPEND function */74/* PSCI v0.2 power state encoding for CPU_SUSPEND function */
73#define PSCI_0_2_POWER_STATE_ID_MASK 0xffff75#define PSCI_0_2_POWER_STATE_ID_MASK 0xffff
@@ -100,6 +102,9 @@ · 26 unmodified lines
100#define PSCI_1_1_RESET_TYPE_SYSTEM_WARM_RESET 0102#define PSCI_1_1_RESET_TYPE_SYSTEM_WARM_RESET 0
101#define PSCI_1_1_RESET_TYPE_VENDOR_START 0x80000000U103#define PSCI_1_1_RESET_TYPE_VENDOR_START 0x80000000U
102 104
105/* PSCI v1.3 hibernate type for SYSTEM_OFF2 */
106#define PSCI_1_3_OFF_TYPE_HIBERNATE_OFF BIT(0)
107
103/* PSCI version decoding (independent of PSCI version) */108/* PSCI version decoding (independent of PSCI version) */
104#define PSCI_VERSION_MAJOR_SHIFT 16109#define PSCI_VERSION_MAJOR_SHIFT 16
105#define PSCI_VERSION_MINOR_MASK \110#define PSCI_VERSION_MINOR_MASK \
kernel/power/hibernate.c+4−1
@@ -685,8 +685,11 @@ static void power_down(void) · 684 unmodified lines
685 }685 }
686 fallthrough;686 fallthrough;
687 case HIBERNATION_SHUTDOWN:687 case HIBERNATION_SHUTDOWN:
688 if (kernel_can_power_off())688 if (kernel_can_power_off()) {
689 entering_platform_hibernation = true;
689 kernel_power_off();690 kernel_power_off();
691 entering_platform_hibernation = false;
692 }
690 break;693 break;
691 }694 }
692 kernel_halt();695 kernel_halt();
tools/testing/selftests/kvm/aarch64/psci_test.c+92−0
@@ -54,6 +54,15 @@ static uint64_t psci_system_suspend(uint64_t entry_addr, uint64_t context_id) · 53 unmodified lines
54 return res.a0;54 return res.a0;
55}55}
56 56
57static uint64_t psci_system_off2(uint64_t type, uint64_t cookie)
58{
59 struct arm_smccc_res res;
60
61 smccc_hvc(PSCI_1_3_FN64_SYSTEM_OFF2, type, cookie, 0, 0, 0, 0, 0, &res);
62
63 return res.a0;
64}
65
57static uint64_t psci_features(uint32_t func_id)66static uint64_t psci_features(uint32_t func_id)
58{67{
59 struct arm_smccc_res res;68 struct arm_smccc_res res;
@@ -188,11 +197,94 @@ static void host_test_system_suspend(void) · 128 unmodified lines
188 kvm_vm_free(vm);197 kvm_vm_free(vm);
189}198}
190 199
200static void guest_test_system_off2(void)
201{
202 uint64_t ret;
203
204 /* assert that SYSTEM_OFF2 is discoverable */
205 GUEST_ASSERT(psci_features(PSCI_1_3_FN_SYSTEM_OFF2) &
206 PSCI_1_3_OFF_TYPE_HIBERNATE_OFF);
207 GUEST_ASSERT(psci_features(PSCI_1_3_FN64_SYSTEM_OFF2) &
208 PSCI_1_3_OFF_TYPE_HIBERNATE_OFF);
209
210 /* With non-zero 'cookie' field, it should fail */
211 ret = psci_system_off2(PSCI_1_3_OFF_TYPE_HIBERNATE_OFF, 1);
212 GUEST_ASSERT(ret == PSCI_RET_INVALID_PARAMS);
213
214 /*
215 * This would normally never return, so KVM sets the return value
216 * to PSCI_RET_INTERNAL_FAILURE. The test case *does* return, so
217 * that it can test both values for HIBERNATE_OFF.
218 */
219 ret = psci_system_off2(PSCI_1_3_OFF_TYPE_HIBERNATE_OFF, 0);
220 GUEST_ASSERT(ret == PSCI_RET_INTERNAL_FAILURE);
221
222 /*
223 * Revision F.b of the PSCI v1.3 specification documents zero as an
224 * alias for HIBERNATE_OFF, since that's the value used in earlier
225 * revisions of the spec and some implementations in the field.
226 */
227 ret = psci_system_off2(0, 1);
228 GUEST_ASSERT(ret == PSCI_RET_INVALID_PARAMS);
229
230 ret = psci_system_off2(0, 0);
231 GUEST_ASSERT(ret == PSCI_RET_INTERNAL_FAILURE);
232
233 GUEST_DONE();
234}
235
236static void host_test_system_off2(void)
237{
238 struct kvm_vcpu *source, *target;
239 struct kvm_mp_state mps;
240 uint64_t psci_version = 0;
241 int nr_shutdowns = 0;
242 struct kvm_run *run;
243 struct ucall uc;
244
245 setup_vm(guest_test_system_off2, &source, &target);
246
247 vcpu_get_reg(target, KVM_REG_ARM_PSCI_VERSION, &psci_version);
248
249 TEST_ASSERT(psci_version >= PSCI_VERSION(1, 3),
250 "Unexpected PSCI version %lu.%lu",
251 PSCI_VERSION_MAJOR(psci_version),
252 PSCI_VERSION_MINOR(psci_version));
253
254 vcpu_power_off(target);
255 run = source->run;
256
257 enter_guest(source);
258 while (run->exit_reason == KVM_EXIT_SYSTEM_EVENT) {
259 TEST_ASSERT(run->system_event.type == KVM_SYSTEM_EVENT_SHUTDOWN,
260 "Unhandled system event: %u (expected: %u)",
261 run->system_event.type, KVM_SYSTEM_EVENT_SHUTDOWN);
262 TEST_ASSERT(run->system_event.ndata >= 1,
263 "Unexpected amount of system event data: %u (expected, >= 1)",
264 run->system_event.ndata);
265 TEST_ASSERT(run->system_event.data[0] & KVM_SYSTEM_EVENT_SHUTDOWN_FLAG_PSCI_OFF2,
266 "PSCI_OFF2 flag not set. Flags %llu (expected %llu)",
267 run->system_event.data[0], KVM_SYSTEM_EVENT_SHUTDOWN_FLAG_PSCI_OFF2);
268
269 nr_shutdowns++;
270
271 /* Restart the vCPU */
272 mps.mp_state = KVM_MP_STATE_RUNNABLE;
273 vcpu_mp_state_set(source, &mps);
274
275 enter_guest(source);
276 }
277
278 TEST_ASSERT(get_ucall(source, &uc) == UCALL_DONE, "Guest did not exit cleanly");
279 TEST_ASSERT(nr_shutdowns == 2, "Two shutdown events were expected, but saw %d", nr_shutdowns);
280}
281
191int main(void)282int main(void)
192{283{
193 TEST_REQUIRE(kvm_has_cap(KVM_CAP_ARM_SYSTEM_SUSPEND));284 TEST_REQUIRE(kvm_has_cap(KVM_CAP_ARM_SYSTEM_SUSPEND));
194 285
195 host_test_cpu_on();286 host_test_cpu_on();
196 host_test_system_suspend();287 host_test_system_suspend();
288 host_test_system_off2();
197 return 0;289 return 0;
198}290}