1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * Floating interrupt tests. 4 * 5 * Copyright 2021 Red Hat Inc 6 * 7 * Authors: 8 * David Hildenbrand <david@redhat.com> 9 */ 10 #include <libcflat.h> 11 #include <asm/asm-offsets.h> 12 #include <asm/interrupt.h> 13 #include <asm/page.h> 14 #include <asm-generic/barrier.h> 15 16 #include <sclp.h> 17 #include <smp.h> 18 #include <alloc_page.h> 19 20 static void wait_for_sclp_int(void) 21 { 22 /* Enable SCLP interrupts on this CPU only. */ 23 ctl_set_bit(0, CTL0_SERVICE_SIGNAL); 24 25 /* Enable external interrupts and go to the wait state. */ 26 wait_for_interrupt(PSW_MASK_EXT); 27 } 28 29 /* 30 * Some KVM versions might mix CPUs when looking for a floating IRQ target, 31 * accidentially detecting a stopped CPU as waiting and resulting in the actually 32 * waiting CPU not getting woken up for the interrupt. 33 */ 34 static void test_wait_state_delivery(void) 35 { 36 struct psw psw; 37 SCCBHeader *h; 38 int ret; 39 40 report_prefix_push("wait state delivery"); 41 42 if (smp_query_num_cpus() < 3) { 43 report_skip("need at least 3 CPUs for this test"); 44 goto out; 45 } 46 47 /* Stop CPU #2. It must succeed because we have at least 3 CPUs */ 48 ret = smp_cpu_stop(2); 49 assert(!ret); 50 51 /* 52 * We're going to perform an SCLP service call but expect the 53 * interrupt on CPU #1 while it is in the wait state. 54 */ 55 sclp_mark_busy(); 56 57 /* Start CPU #1 and let it wait for the interrupt. */ 58 psw.mask = extract_psw_mask(); 59 psw.addr = (unsigned long)wait_for_sclp_int; 60 ret = smp_cpu_setup(1, psw); 61 /* This must not fail because we have at least 3 CPUs */ 62 assert(!ret); 63 64 /* 65 * We'd have to jump trough some hoops to sense e.g., via SIGP 66 * CONDITIONAL EMERGENCY SIGNAL if CPU #1 is already in the 67 * wait state. 68 * 69 * Although not completely reliable, use SIGP SENSE RUNNING STATUS 70 * until not reported as running -- after all, our SCLP processing 71 * will take some time as well and smp_cpu_setup() returns when we're 72 * either already in wait_for_sclp_int() or just about to execute it. 73 */ 74 while(smp_sense_running_status(1)); 75 76 h = alloc_pages_flags(0, AREA_DMA31); 77 h->length = 4096; 78 ret = servc(SCLP_CMDW_READ_CPU_INFO, __pa(h)); 79 if (ret) { 80 sclp_clear_busy(); 81 report_fail("SCLP_CMDW_READ_CPU_INFO failed"); 82 goto out_destroy; 83 } 84 85 /* 86 * Wait until the interrupt gets delivered on CPU #1, marking the 87 * SCLP requests as done. 88 */ 89 sclp_wait_busy(); 90 91 report(true, "sclp interrupt delivered"); 92 93 out_destroy: 94 free_page(h); 95 smp_cpu_destroy(1); 96 out: 97 report_prefix_pop(); 98 } 99 100 int main(void) 101 { 102 report_prefix_push("firq"); 103 104 test_wait_state_delivery(); 105 106 report_prefix_pop(); 107 return report_summary(); 108 } 109