1 /* 2 * Tests sigp emulation 3 * 4 * Copyright 2019 IBM Corp. 5 * 6 * Authors: 7 * Janosch Frank <frankja@linux.ibm.com> 8 * 9 * This code is free software; you can redistribute it and/or modify it 10 * under the terms of the GNU General Public License version 2. 11 */ 12 #include <libcflat.h> 13 #include <asm/asm-offsets.h> 14 #include <asm/interrupt.h> 15 #include <asm/page.h> 16 #include <asm/facility.h> 17 #include <asm-generic/barrier.h> 18 #include <asm/sigp.h> 19 20 #include <smp.h> 21 #include <alloc_page.h> 22 23 static int testflag = 0; 24 25 static void cpu_loop(void) 26 { 27 for (;;) {} 28 } 29 30 static void test_func(void) 31 { 32 testflag = 1; 33 mb(); 34 cpu_loop(); 35 } 36 37 static void test_start(void) 38 { 39 struct psw psw; 40 psw.mask = extract_psw_mask(); 41 psw.addr = (unsigned long)test_func; 42 43 smp_cpu_setup(1, psw); 44 while (!testflag) { 45 mb(); 46 } 47 report(1, "start"); 48 } 49 50 static void test_stop(void) 51 { 52 smp_cpu_stop(1); 53 /* 54 * The smp library waits for the CPU to shut down, but let's 55 * also do it here, so we don't rely on the library 56 * implementation 57 */ 58 while (!smp_cpu_stopped(1)) {} 59 report(1, "stop"); 60 } 61 62 static void test_stop_store_status(void) 63 { 64 struct cpu *cpu = smp_cpu_from_addr(1); 65 struct lowcore *lc = (void *)0x0; 66 67 report_prefix_push("stop store status"); 68 lc->prefix_sa = 0; 69 lc->grs_sa[15] = 0; 70 smp_cpu_stop_store_status(1); 71 mb(); 72 report(lc->prefix_sa == (uint32_t)(uintptr_t)cpu->lowcore, "prefix"); 73 report(lc->grs_sa[15], "stack"); 74 report_prefix_pop(); 75 } 76 77 static void test_store_status(void) 78 { 79 struct cpu_status *status = alloc_pages(1); 80 uint32_t r; 81 82 report_prefix_push("store status at address"); 83 memset(status, 0, PAGE_SIZE * 2); 84 85 report_prefix_push("running"); 86 smp_cpu_restart(1); 87 sigp(1, SIGP_STORE_STATUS_AT_ADDRESS, (uintptr_t)status, &r); 88 report(r == SIGP_STATUS_INCORRECT_STATE, "incorrect state"); 89 report(!memcmp(status, (void *)status + PAGE_SIZE, PAGE_SIZE), 90 "status not written"); 91 report_prefix_pop(); 92 93 memset(status, 0, PAGE_SIZE); 94 report_prefix_push("stopped"); 95 smp_cpu_stop(1); 96 sigp(1, SIGP_STORE_STATUS_AT_ADDRESS, (uintptr_t)status, NULL); 97 while (!status->prefix) { mb(); } 98 report(1, "status written"); 99 free_pages(status, PAGE_SIZE * 2); 100 report_prefix_pop(); 101 102 report_prefix_pop(); 103 } 104 105 static void ecall(void) 106 { 107 unsigned long mask; 108 struct lowcore *lc = (void *)0x0; 109 110 expect_ext_int(); 111 ctl_set_bit(0, 13); 112 mask = extract_psw_mask(); 113 mask |= PSW_MASK_EXT; 114 load_psw_mask(mask); 115 testflag = 1; 116 while (lc->ext_int_code != 0x1202) { mb(); } 117 report(1, "ecall"); 118 testflag= 1; 119 } 120 121 static void test_ecall(void) 122 { 123 struct psw psw; 124 psw.mask = extract_psw_mask(); 125 psw.addr = (unsigned long)ecall; 126 127 report_prefix_push("ecall"); 128 testflag= 0; 129 smp_cpu_destroy(1); 130 131 smp_cpu_setup(1, psw); 132 while (!testflag) { mb(); } 133 testflag= 0; 134 sigp(1, SIGP_EXTERNAL_CALL, 0, NULL); 135 while(!testflag) {mb();} 136 smp_cpu_stop(1); 137 report_prefix_pop(); 138 } 139 140 static void emcall(void) 141 { 142 unsigned long mask; 143 struct lowcore *lc = (void *)0x0; 144 145 expect_ext_int(); 146 ctl_set_bit(0, 14); 147 mask = extract_psw_mask(); 148 mask |= PSW_MASK_EXT; 149 load_psw_mask(mask); 150 testflag= 1; 151 while (lc->ext_int_code != 0x1201) { mb(); } 152 report(1, "ecall"); 153 testflag = 1; 154 } 155 156 static void test_emcall(void) 157 { 158 struct psw psw; 159 psw.mask = extract_psw_mask(); 160 psw.addr = (unsigned long)emcall; 161 162 report_prefix_push("emcall"); 163 testflag= 0; 164 smp_cpu_destroy(1); 165 166 smp_cpu_setup(1, psw); 167 while (!testflag) { mb(); } 168 testflag= 0; 169 sigp(1, SIGP_EMERGENCY_SIGNAL, 0, NULL); 170 while(!testflag) { mb(); } 171 smp_cpu_stop(1); 172 report_prefix_pop(); 173 } 174 175 static void test_reset_initial(void) 176 { 177 struct cpu_status *status = alloc_pages(0); 178 struct psw psw; 179 180 psw.mask = extract_psw_mask(); 181 psw.addr = (unsigned long)test_func; 182 183 report_prefix_push("reset initial"); 184 smp_cpu_setup(1, psw); 185 186 sigp_retry(1, SIGP_INITIAL_CPU_RESET, 0, NULL); 187 sigp(1, SIGP_STORE_STATUS_AT_ADDRESS, (uintptr_t)status, NULL); 188 189 report_prefix_push("clear"); 190 report(!status->psw.mask && !status->psw.addr, "psw"); 191 report(!status->prefix, "prefix"); 192 report(!status->fpc, "fpc"); 193 report(!status->cputm, "cpu timer"); 194 report(!status->todpr, "todpr"); 195 report_prefix_pop(); 196 197 report_prefix_push("initialized"); 198 report(status->crs[0] == 0xE0UL, "cr0 == 0xE0"); 199 report(status->crs[14] == 0xC2000000UL, "cr14 == 0xC2000000"); 200 report_prefix_pop(); 201 202 report(smp_cpu_stopped(1), "cpu stopped"); 203 free_pages(status, PAGE_SIZE); 204 report_prefix_pop(); 205 } 206 207 static void test_reset(void) 208 { 209 struct psw psw; 210 211 psw.mask = extract_psw_mask(); 212 psw.addr = (unsigned long)test_func; 213 214 report_prefix_push("cpu reset"); 215 smp_cpu_setup(1, psw); 216 217 sigp_retry(1, SIGP_CPU_RESET, 0, NULL); 218 report(smp_cpu_stopped(1), "cpu stopped"); 219 report_prefix_pop(); 220 } 221 222 int main(void) 223 { 224 report_prefix_push("smp"); 225 226 if (smp_query_num_cpus() == 1) { 227 report_skip("need at least 2 cpus for this test"); 228 goto done; 229 } 230 231 test_start(); 232 test_stop(); 233 test_stop_store_status(); 234 test_store_status(); 235 test_ecall(); 236 test_emcall(); 237 test_reset(); 238 test_reset_initial(); 239 240 done: 241 report_prefix_pop(); 242 return report_summary(); 243 } 244