110ec5117SAlexander Graf /* 2aea1e885SBlue Swirl * S/390 misc helper routines 310ec5117SAlexander Graf * 4defb0e31SAlexander Graf * Copyright (c) 2009 Ulrich Hecht 510ec5117SAlexander Graf * Copyright (c) 2009 Alexander Graf 610ec5117SAlexander Graf * 710ec5117SAlexander Graf * This library is free software; you can redistribute it and/or 810ec5117SAlexander Graf * modify it under the terms of the GNU Lesser General Public 910ec5117SAlexander Graf * License as published by the Free Software Foundation; either 1010ec5117SAlexander Graf * version 2 of the License, or (at your option) any later version. 1110ec5117SAlexander Graf * 1210ec5117SAlexander Graf * This library is distributed in the hope that it will be useful, 1310ec5117SAlexander Graf * but WITHOUT ANY WARRANTY; without even the implied warranty of 1410ec5117SAlexander Graf * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1510ec5117SAlexander Graf * Lesser General Public License for more details. 1610ec5117SAlexander Graf * 1710ec5117SAlexander Graf * You should have received a copy of the GNU Lesser General Public 1870539e18SBlue Swirl * License along with this library; if not, see <http://www.gnu.org/licenses/>. 1910ec5117SAlexander Graf */ 2010ec5117SAlexander Graf 213e457172SBlue Swirl #include "cpu.h" 22022c62cbSPaolo Bonzini #include "exec/memory.h" 231de7afc9SPaolo Bonzini #include "qemu/host-utils.h" 243208afbeSLluís Vilanova #include "helper.h" 25defb0e31SAlexander Graf #include <string.h> 269c17d615SPaolo Bonzini #include "sysemu/kvm.h" 271de7afc9SPaolo Bonzini #include "qemu/timer.h" 28af2be207SJan Kiszka #ifdef CONFIG_KVM 29af2be207SJan Kiszka #include <linux/kvm.h> 30af2be207SJan Kiszka #endif 3110ec5117SAlexander Graf 321864b94aSAlexander Graf #if !defined(CONFIG_USER_ONLY) 33022c62cbSPaolo Bonzini #include "exec/softmmu_exec.h" 349c17d615SPaolo Bonzini #include "sysemu/sysemu.h" 3510ec5117SAlexander Graf #endif 36d5a43964SAlexander Graf 37defb0e31SAlexander Graf /* #define DEBUG_HELPER */ 38defb0e31SAlexander Graf #ifdef DEBUG_HELPER 39defb0e31SAlexander Graf #define HELPER_LOG(x...) qemu_log(x) 40defb0e31SAlexander Graf #else 41defb0e31SAlexander Graf #define HELPER_LOG(x...) 42defb0e31SAlexander Graf #endif 43defb0e31SAlexander Graf 44b4e2bd35SRichard Henderson /* Raise an exception dynamically from a helper function. */ 45b4e2bd35SRichard Henderson void QEMU_NORETURN runtime_exception(CPUS390XState *env, int excp, 46b4e2bd35SRichard Henderson uintptr_t retaddr) 47b4e2bd35SRichard Henderson { 48b4e2bd35SRichard Henderson int t; 49b4e2bd35SRichard Henderson 50b4e2bd35SRichard Henderson env->exception_index = EXCP_PGM; 51b4e2bd35SRichard Henderson env->int_pgm_code = excp; 52b4e2bd35SRichard Henderson 53b4e2bd35SRichard Henderson /* Use the (ultimate) callers address to find the insn that trapped. */ 54b4e2bd35SRichard Henderson cpu_restore_state(env, retaddr); 55b4e2bd35SRichard Henderson 56b4e2bd35SRichard Henderson /* Advance past the insn. */ 57b4e2bd35SRichard Henderson t = cpu_ldub_code(env, env->psw.addr); 58b4e2bd35SRichard Henderson env->int_pgm_ilen = t = get_ilen(t); 59b4e2bd35SRichard Henderson env->psw.addr += 2 * t; 60b4e2bd35SRichard Henderson 61b4e2bd35SRichard Henderson cpu_loop_exit(env); 62b4e2bd35SRichard Henderson } 63b4e2bd35SRichard Henderson 64d5a103cdSRichard Henderson /* Raise an exception statically from a TB. */ 65089f5c06SBlue Swirl void HELPER(exception)(CPUS390XState *env, uint32_t excp) 66defb0e31SAlexander Graf { 6771e47088SBlue Swirl HELPER_LOG("%s: exception %d\n", __func__, excp); 68defb0e31SAlexander Graf env->exception_index = excp; 691162c041SBlue Swirl cpu_loop_exit(env); 70defb0e31SAlexander Graf } 71defb0e31SAlexander Graf 72defb0e31SAlexander Graf #ifndef CONFIG_USER_ONLY 73d5a103cdSRichard Henderson void program_interrupt(CPUS390XState *env, uint32_t code, int ilen) 74defb0e31SAlexander Graf { 750d404541SRichard Henderson qemu_log_mask(CPU_LOG_INT, "program interrupt at %#" PRIx64 "\n", 760d404541SRichard Henderson env->psw.addr); 77defb0e31SAlexander Graf 78defb0e31SAlexander Graf if (kvm_enabled()) { 79af2be207SJan Kiszka #ifdef CONFIG_KVM 801bc22652SAndreas Färber kvm_s390_interrupt(s390_env_get_cpu(env), KVM_S390_PROGRAM_INT, code); 81af2be207SJan Kiszka #endif 82defb0e31SAlexander Graf } else { 83defb0e31SAlexander Graf env->int_pgm_code = code; 84d5a103cdSRichard Henderson env->int_pgm_ilen = ilen; 85defb0e31SAlexander Graf env->exception_index = EXCP_PGM; 861162c041SBlue Swirl cpu_loop_exit(env); 87defb0e31SAlexander Graf } 88defb0e31SAlexander Graf } 89defb0e31SAlexander Graf 90defb0e31SAlexander Graf /* SCLP service call */ 91089f5c06SBlue Swirl uint32_t HELPER(servc)(CPUS390XState *env, uint32_t r1, uint64_t r2) 92defb0e31SAlexander Graf { 939abf567dSChristian Borntraeger int r; 94defb0e31SAlexander Graf 95f6c98f92SHeinz Graalfs r = sclp_service_call(r1, r2); 969abf567dSChristian Borntraeger if (r < 0) { 979abf567dSChristian Borntraeger program_interrupt(env, -r, 4); 98d5a43964SAlexander Graf return 0; 99d5a43964SAlexander Graf } 1009abf567dSChristian Borntraeger return r; 1019abf567dSChristian Borntraeger } 102defb0e31SAlexander Graf 103defb0e31SAlexander Graf /* DIAG */ 104089f5c06SBlue Swirl uint64_t HELPER(diag)(CPUS390XState *env, uint32_t num, uint64_t mem, 105089f5c06SBlue Swirl uint64_t code) 106defb0e31SAlexander Graf { 107defb0e31SAlexander Graf uint64_t r; 108defb0e31SAlexander Graf 109defb0e31SAlexander Graf switch (num) { 110defb0e31SAlexander Graf case 0x500: 111defb0e31SAlexander Graf /* KVM hypercall */ 112defb0e31SAlexander Graf r = s390_virtio_hypercall(env, mem, code); 113defb0e31SAlexander Graf break; 114defb0e31SAlexander Graf case 0x44: 115defb0e31SAlexander Graf /* yield */ 116defb0e31SAlexander Graf r = 0; 117defb0e31SAlexander Graf break; 118defb0e31SAlexander Graf case 0x308: 119defb0e31SAlexander Graf /* ipl */ 120defb0e31SAlexander Graf r = 0; 121defb0e31SAlexander Graf break; 122defb0e31SAlexander Graf default: 123defb0e31SAlexander Graf r = -1; 124defb0e31SAlexander Graf break; 125defb0e31SAlexander Graf } 126defb0e31SAlexander Graf 127defb0e31SAlexander Graf if (r) { 128d5a103cdSRichard Henderson program_interrupt(env, PGM_OPERATION, ILEN_LATER_INC); 129defb0e31SAlexander Graf } 130defb0e31SAlexander Graf 131defb0e31SAlexander Graf return r; 132defb0e31SAlexander Graf } 133defb0e31SAlexander Graf 134defb0e31SAlexander Graf /* Store CPU ID */ 135089f5c06SBlue Swirl void HELPER(stidp)(CPUS390XState *env, uint64_t a1) 136defb0e31SAlexander Graf { 137089f5c06SBlue Swirl cpu_stq_data(env, a1, env->cpu_num); 138defb0e31SAlexander Graf } 139defb0e31SAlexander Graf 140defb0e31SAlexander Graf /* Set Prefix */ 141089f5c06SBlue Swirl void HELPER(spx)(CPUS390XState *env, uint64_t a1) 142defb0e31SAlexander Graf { 143defb0e31SAlexander Graf uint32_t prefix; 144defb0e31SAlexander Graf 145089f5c06SBlue Swirl prefix = cpu_ldl_data(env, a1); 146defb0e31SAlexander Graf env->psa = prefix & 0xfffff000; 147defb0e31SAlexander Graf qemu_log("prefix: %#x\n", prefix); 148defb0e31SAlexander Graf tlb_flush_page(env, 0); 149defb0e31SAlexander Graf tlb_flush_page(env, TARGET_PAGE_SIZE); 150defb0e31SAlexander Graf } 151defb0e31SAlexander Graf 152defb0e31SAlexander Graf /* Set Clock */ 153defb0e31SAlexander Graf uint32_t HELPER(sck)(uint64_t a1) 154defb0e31SAlexander Graf { 155defb0e31SAlexander Graf /* XXX not implemented - is it necessary? */ 156defb0e31SAlexander Graf 157defb0e31SAlexander Graf return 0; 158defb0e31SAlexander Graf } 159defb0e31SAlexander Graf 160a4e3ad19SAndreas Färber static inline uint64_t clock_value(CPUS390XState *env) 161defb0e31SAlexander Graf { 162defb0e31SAlexander Graf uint64_t time; 163defb0e31SAlexander Graf 164defb0e31SAlexander Graf time = env->tod_offset + 165defb0e31SAlexander Graf time2tod(qemu_get_clock_ns(vm_clock) - env->tod_basetime); 166defb0e31SAlexander Graf 167defb0e31SAlexander Graf return time; 168defb0e31SAlexander Graf } 169defb0e31SAlexander Graf 170defb0e31SAlexander Graf /* Store Clock */ 171089f5c06SBlue Swirl uint32_t HELPER(stck)(CPUS390XState *env, uint64_t a1) 172defb0e31SAlexander Graf { 173089f5c06SBlue Swirl cpu_stq_data(env, a1, clock_value(env)); 174defb0e31SAlexander Graf 175defb0e31SAlexander Graf return 0; 176defb0e31SAlexander Graf } 177defb0e31SAlexander Graf 178defb0e31SAlexander Graf /* Store Clock Extended */ 179089f5c06SBlue Swirl uint32_t HELPER(stcke)(CPUS390XState *env, uint64_t a1) 180defb0e31SAlexander Graf { 181089f5c06SBlue Swirl cpu_stb_data(env, a1, 0); 182defb0e31SAlexander Graf /* basically the same value as stck */ 183089f5c06SBlue Swirl cpu_stq_data(env, a1 + 1, clock_value(env) | env->cpu_num); 184defb0e31SAlexander Graf /* more fine grained than stck */ 185089f5c06SBlue Swirl cpu_stq_data(env, a1 + 9, 0); 186defb0e31SAlexander Graf /* XXX programmable fields */ 187089f5c06SBlue Swirl cpu_stw_data(env, a1 + 17, 0); 188defb0e31SAlexander Graf 189defb0e31SAlexander Graf return 0; 190defb0e31SAlexander Graf } 191defb0e31SAlexander Graf 192defb0e31SAlexander Graf /* Set Clock Comparator */ 193089f5c06SBlue Swirl void HELPER(sckc)(CPUS390XState *env, uint64_t a1) 194defb0e31SAlexander Graf { 195089f5c06SBlue Swirl uint64_t time = cpu_ldq_data(env, a1); 196defb0e31SAlexander Graf 197defb0e31SAlexander Graf if (time == -1ULL) { 198defb0e31SAlexander Graf return; 199defb0e31SAlexander Graf } 200defb0e31SAlexander Graf 201defb0e31SAlexander Graf /* difference between now and then */ 202defb0e31SAlexander Graf time -= clock_value(env); 203defb0e31SAlexander Graf /* nanoseconds */ 204defb0e31SAlexander Graf time = (time * 125) >> 9; 205defb0e31SAlexander Graf 206defb0e31SAlexander Graf qemu_mod_timer(env->tod_timer, qemu_get_clock_ns(vm_clock) + time); 207defb0e31SAlexander Graf } 208defb0e31SAlexander Graf 209defb0e31SAlexander Graf /* Store Clock Comparator */ 210089f5c06SBlue Swirl void HELPER(stckc)(CPUS390XState *env, uint64_t a1) 211defb0e31SAlexander Graf { 212defb0e31SAlexander Graf /* XXX implement */ 213089f5c06SBlue Swirl cpu_stq_data(env, a1, 0); 214defb0e31SAlexander Graf } 215defb0e31SAlexander Graf 216defb0e31SAlexander Graf /* Set CPU Timer */ 217089f5c06SBlue Swirl void HELPER(spt)(CPUS390XState *env, uint64_t a1) 218defb0e31SAlexander Graf { 219089f5c06SBlue Swirl uint64_t time = cpu_ldq_data(env, a1); 220defb0e31SAlexander Graf 221defb0e31SAlexander Graf if (time == -1ULL) { 222defb0e31SAlexander Graf return; 223defb0e31SAlexander Graf } 224defb0e31SAlexander Graf 225defb0e31SAlexander Graf /* nanoseconds */ 226defb0e31SAlexander Graf time = (time * 125) >> 9; 227defb0e31SAlexander Graf 228defb0e31SAlexander Graf qemu_mod_timer(env->cpu_timer, qemu_get_clock_ns(vm_clock) + time); 229defb0e31SAlexander Graf } 230defb0e31SAlexander Graf 231defb0e31SAlexander Graf /* Store CPU Timer */ 232089f5c06SBlue Swirl void HELPER(stpt)(CPUS390XState *env, uint64_t a1) 233defb0e31SAlexander Graf { 234defb0e31SAlexander Graf /* XXX implement */ 235089f5c06SBlue Swirl cpu_stq_data(env, a1, 0); 236defb0e31SAlexander Graf } 237defb0e31SAlexander Graf 238defb0e31SAlexander Graf /* Store System Information */ 239089f5c06SBlue Swirl uint32_t HELPER(stsi)(CPUS390XState *env, uint64_t a0, uint32_t r0, 240089f5c06SBlue Swirl uint32_t r1) 241defb0e31SAlexander Graf { 242defb0e31SAlexander Graf int cc = 0; 243defb0e31SAlexander Graf int sel1, sel2; 244defb0e31SAlexander Graf 245defb0e31SAlexander Graf if ((r0 & STSI_LEVEL_MASK) <= STSI_LEVEL_3 && 246defb0e31SAlexander Graf ((r0 & STSI_R0_RESERVED_MASK) || (r1 & STSI_R1_RESERVED_MASK))) { 247defb0e31SAlexander Graf /* valid function code, invalid reserved bits */ 248defb0e31SAlexander Graf program_interrupt(env, PGM_SPECIFICATION, 2); 249defb0e31SAlexander Graf } 250defb0e31SAlexander Graf 251defb0e31SAlexander Graf sel1 = r0 & STSI_R0_SEL1_MASK; 252defb0e31SAlexander Graf sel2 = r1 & STSI_R1_SEL2_MASK; 253defb0e31SAlexander Graf 254defb0e31SAlexander Graf /* XXX: spec exception if sysib is not 4k-aligned */ 255defb0e31SAlexander Graf 256defb0e31SAlexander Graf switch (r0 & STSI_LEVEL_MASK) { 257defb0e31SAlexander Graf case STSI_LEVEL_1: 258defb0e31SAlexander Graf if ((sel1 == 1) && (sel2 == 1)) { 259defb0e31SAlexander Graf /* Basic Machine Configuration */ 260defb0e31SAlexander Graf struct sysib_111 sysib; 261defb0e31SAlexander Graf 262defb0e31SAlexander Graf memset(&sysib, 0, sizeof(sysib)); 263defb0e31SAlexander Graf ebcdic_put(sysib.manuf, "QEMU ", 16); 264defb0e31SAlexander Graf /* same as machine type number in STORE CPU ID */ 265defb0e31SAlexander Graf ebcdic_put(sysib.type, "QEMU", 4); 266defb0e31SAlexander Graf /* same as model number in STORE CPU ID */ 267defb0e31SAlexander Graf ebcdic_put(sysib.model, "QEMU ", 16); 268defb0e31SAlexander Graf ebcdic_put(sysib.sequence, "QEMU ", 16); 269defb0e31SAlexander Graf ebcdic_put(sysib.plant, "QEMU", 4); 270defb0e31SAlexander Graf cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1); 271defb0e31SAlexander Graf } else if ((sel1 == 2) && (sel2 == 1)) { 272defb0e31SAlexander Graf /* Basic Machine CPU */ 273defb0e31SAlexander Graf struct sysib_121 sysib; 274defb0e31SAlexander Graf 275defb0e31SAlexander Graf memset(&sysib, 0, sizeof(sysib)); 276defb0e31SAlexander Graf /* XXX make different for different CPUs? */ 277defb0e31SAlexander Graf ebcdic_put(sysib.sequence, "QEMUQEMUQEMUQEMU", 16); 278defb0e31SAlexander Graf ebcdic_put(sysib.plant, "QEMU", 4); 279defb0e31SAlexander Graf stw_p(&sysib.cpu_addr, env->cpu_num); 280defb0e31SAlexander Graf cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1); 281defb0e31SAlexander Graf } else if ((sel1 == 2) && (sel2 == 2)) { 282defb0e31SAlexander Graf /* Basic Machine CPUs */ 283defb0e31SAlexander Graf struct sysib_122 sysib; 284defb0e31SAlexander Graf 285defb0e31SAlexander Graf memset(&sysib, 0, sizeof(sysib)); 286defb0e31SAlexander Graf stl_p(&sysib.capability, 0x443afc29); 287defb0e31SAlexander Graf /* XXX change when SMP comes */ 288defb0e31SAlexander Graf stw_p(&sysib.total_cpus, 1); 289defb0e31SAlexander Graf stw_p(&sysib.active_cpus, 1); 290defb0e31SAlexander Graf stw_p(&sysib.standby_cpus, 0); 291defb0e31SAlexander Graf stw_p(&sysib.reserved_cpus, 0); 292defb0e31SAlexander Graf cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1); 293defb0e31SAlexander Graf } else { 294defb0e31SAlexander Graf cc = 3; 295defb0e31SAlexander Graf } 296defb0e31SAlexander Graf break; 297defb0e31SAlexander Graf case STSI_LEVEL_2: 298defb0e31SAlexander Graf { 299defb0e31SAlexander Graf if ((sel1 == 2) && (sel2 == 1)) { 300defb0e31SAlexander Graf /* LPAR CPU */ 301defb0e31SAlexander Graf struct sysib_221 sysib; 302defb0e31SAlexander Graf 303defb0e31SAlexander Graf memset(&sysib, 0, sizeof(sysib)); 304defb0e31SAlexander Graf /* XXX make different for different CPUs? */ 305defb0e31SAlexander Graf ebcdic_put(sysib.sequence, "QEMUQEMUQEMUQEMU", 16); 306defb0e31SAlexander Graf ebcdic_put(sysib.plant, "QEMU", 4); 307defb0e31SAlexander Graf stw_p(&sysib.cpu_addr, env->cpu_num); 308defb0e31SAlexander Graf stw_p(&sysib.cpu_id, 0); 309defb0e31SAlexander Graf cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1); 310defb0e31SAlexander Graf } else if ((sel1 == 2) && (sel2 == 2)) { 311defb0e31SAlexander Graf /* LPAR CPUs */ 312defb0e31SAlexander Graf struct sysib_222 sysib; 313defb0e31SAlexander Graf 314defb0e31SAlexander Graf memset(&sysib, 0, sizeof(sysib)); 315defb0e31SAlexander Graf stw_p(&sysib.lpar_num, 0); 316defb0e31SAlexander Graf sysib.lcpuc = 0; 317defb0e31SAlexander Graf /* XXX change when SMP comes */ 318defb0e31SAlexander Graf stw_p(&sysib.total_cpus, 1); 319defb0e31SAlexander Graf stw_p(&sysib.conf_cpus, 1); 320defb0e31SAlexander Graf stw_p(&sysib.standby_cpus, 0); 321defb0e31SAlexander Graf stw_p(&sysib.reserved_cpus, 0); 322defb0e31SAlexander Graf ebcdic_put(sysib.name, "QEMU ", 8); 323defb0e31SAlexander Graf stl_p(&sysib.caf, 1000); 324defb0e31SAlexander Graf stw_p(&sysib.dedicated_cpus, 0); 325defb0e31SAlexander Graf stw_p(&sysib.shared_cpus, 0); 326defb0e31SAlexander Graf cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1); 327defb0e31SAlexander Graf } else { 328defb0e31SAlexander Graf cc = 3; 329defb0e31SAlexander Graf } 330defb0e31SAlexander Graf break; 331defb0e31SAlexander Graf } 332defb0e31SAlexander Graf case STSI_LEVEL_3: 333defb0e31SAlexander Graf { 334defb0e31SAlexander Graf if ((sel1 == 2) && (sel2 == 2)) { 335defb0e31SAlexander Graf /* VM CPUs */ 336defb0e31SAlexander Graf struct sysib_322 sysib; 337defb0e31SAlexander Graf 338defb0e31SAlexander Graf memset(&sysib, 0, sizeof(sysib)); 339defb0e31SAlexander Graf sysib.count = 1; 340defb0e31SAlexander Graf /* XXX change when SMP comes */ 341defb0e31SAlexander Graf stw_p(&sysib.vm[0].total_cpus, 1); 342defb0e31SAlexander Graf stw_p(&sysib.vm[0].conf_cpus, 1); 343defb0e31SAlexander Graf stw_p(&sysib.vm[0].standby_cpus, 0); 344defb0e31SAlexander Graf stw_p(&sysib.vm[0].reserved_cpus, 0); 345defb0e31SAlexander Graf ebcdic_put(sysib.vm[0].name, "KVMguest", 8); 346defb0e31SAlexander Graf stl_p(&sysib.vm[0].caf, 1000); 347defb0e31SAlexander Graf ebcdic_put(sysib.vm[0].cpi, "KVM/Linux ", 16); 348defb0e31SAlexander Graf cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1); 349defb0e31SAlexander Graf } else { 350defb0e31SAlexander Graf cc = 3; 351defb0e31SAlexander Graf } 352defb0e31SAlexander Graf break; 353defb0e31SAlexander Graf } 354defb0e31SAlexander Graf case STSI_LEVEL_CURRENT: 355defb0e31SAlexander Graf env->regs[0] = STSI_LEVEL_3; 356defb0e31SAlexander Graf break; 357defb0e31SAlexander Graf default: 358defb0e31SAlexander Graf cc = 3; 359defb0e31SAlexander Graf break; 360defb0e31SAlexander Graf } 361defb0e31SAlexander Graf 362defb0e31SAlexander Graf return cc; 363defb0e31SAlexander Graf } 364defb0e31SAlexander Graf 365089f5c06SBlue Swirl uint32_t HELPER(sigp)(CPUS390XState *env, uint64_t order_code, uint32_t r1, 366089f5c06SBlue Swirl uint64_t cpu_addr) 367defb0e31SAlexander Graf { 368defb0e31SAlexander Graf int cc = 0; 369defb0e31SAlexander Graf 370defb0e31SAlexander Graf HELPER_LOG("%s: %016" PRIx64 " %08x %016" PRIx64 "\n", 37171e47088SBlue Swirl __func__, order_code, r1, cpu_addr); 372defb0e31SAlexander Graf 373defb0e31SAlexander Graf /* Remember: Use "R1 or R1 + 1, whichever is the odd-numbered register" 374defb0e31SAlexander Graf as parameter (input). Status (output) is always R1. */ 375defb0e31SAlexander Graf 376defb0e31SAlexander Graf switch (order_code) { 377defb0e31SAlexander Graf case SIGP_SET_ARCH: 378defb0e31SAlexander Graf /* switch arch */ 379defb0e31SAlexander Graf break; 380defb0e31SAlexander Graf case SIGP_SENSE: 381defb0e31SAlexander Graf /* enumerate CPU status */ 382defb0e31SAlexander Graf if (cpu_addr) { 383defb0e31SAlexander Graf /* XXX implement when SMP comes */ 384defb0e31SAlexander Graf return 3; 385defb0e31SAlexander Graf } 386defb0e31SAlexander Graf env->regs[r1] &= 0xffffffff00000000ULL; 387defb0e31SAlexander Graf cc = 1; 388defb0e31SAlexander Graf break; 3891864b94aSAlexander Graf #if !defined(CONFIG_USER_ONLY) 3901864b94aSAlexander Graf case SIGP_RESTART: 3911864b94aSAlexander Graf qemu_system_reset_request(); 3921864b94aSAlexander Graf cpu_loop_exit(env); 3931864b94aSAlexander Graf break; 3941864b94aSAlexander Graf case SIGP_STOP: 3951864b94aSAlexander Graf qemu_system_shutdown_request(); 3961864b94aSAlexander Graf cpu_loop_exit(env); 3971864b94aSAlexander Graf break; 3981864b94aSAlexander Graf #endif 399defb0e31SAlexander Graf default: 400defb0e31SAlexander Graf /* unknown sigp */ 401defb0e31SAlexander Graf fprintf(stderr, "XXX unknown sigp: 0x%" PRIx64 "\n", order_code); 402defb0e31SAlexander Graf cc = 3; 403defb0e31SAlexander Graf } 404defb0e31SAlexander Graf 405defb0e31SAlexander Graf return cc; 406defb0e31SAlexander Graf } 407defb0e31SAlexander Graf #endif 408