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" 34f0778475SChristian Borntraeger #include "sysemu/cpus.h" 359c17d615SPaolo Bonzini #include "sysemu/sysemu.h" 3640fa5264SHeinz Graalfs #include "hw/s390x/ebcdic.h" 3710ec5117SAlexander Graf #endif 38d5a43964SAlexander Graf 39defb0e31SAlexander Graf /* #define DEBUG_HELPER */ 40defb0e31SAlexander Graf #ifdef DEBUG_HELPER 41defb0e31SAlexander Graf #define HELPER_LOG(x...) qemu_log(x) 42defb0e31SAlexander Graf #else 43defb0e31SAlexander Graf #define HELPER_LOG(x...) 44defb0e31SAlexander Graf #endif 45defb0e31SAlexander Graf 46b4e2bd35SRichard Henderson /* Raise an exception dynamically from a helper function. */ 47b4e2bd35SRichard Henderson void QEMU_NORETURN runtime_exception(CPUS390XState *env, int excp, 48b4e2bd35SRichard Henderson uintptr_t retaddr) 49b4e2bd35SRichard Henderson { 5027103424SAndreas Färber CPUState *cs = CPU(s390_env_get_cpu(env)); 51b4e2bd35SRichard Henderson int t; 52b4e2bd35SRichard Henderson 5327103424SAndreas Färber cs->exception_index = EXCP_PGM; 54b4e2bd35SRichard Henderson env->int_pgm_code = excp; 55b4e2bd35SRichard Henderson 56b4e2bd35SRichard Henderson /* Use the (ultimate) callers address to find the insn that trapped. */ 573f38f309SAndreas Färber cpu_restore_state(cs, retaddr); 58b4e2bd35SRichard Henderson 59b4e2bd35SRichard Henderson /* Advance past the insn. */ 60b4e2bd35SRichard Henderson t = cpu_ldub_code(env, env->psw.addr); 61b4e2bd35SRichard Henderson env->int_pgm_ilen = t = get_ilen(t); 62b4e2bd35SRichard Henderson env->psw.addr += 2 * t; 63b4e2bd35SRichard Henderson 645638d180SAndreas Färber cpu_loop_exit(cs); 65b4e2bd35SRichard Henderson } 66b4e2bd35SRichard Henderson 67d5a103cdSRichard Henderson /* Raise an exception statically from a TB. */ 68089f5c06SBlue Swirl void HELPER(exception)(CPUS390XState *env, uint32_t excp) 69defb0e31SAlexander Graf { 7027103424SAndreas Färber CPUState *cs = CPU(s390_env_get_cpu(env)); 7127103424SAndreas Färber 7271e47088SBlue Swirl HELPER_LOG("%s: exception %d\n", __func__, excp); 7327103424SAndreas Färber cs->exception_index = excp; 745638d180SAndreas Färber cpu_loop_exit(cs); 75defb0e31SAlexander Graf } 76defb0e31SAlexander Graf 77defb0e31SAlexander Graf #ifndef CONFIG_USER_ONLY 78a158986dSStefan Weil 79d5a103cdSRichard Henderson void program_interrupt(CPUS390XState *env, uint32_t code, int ilen) 80defb0e31SAlexander Graf { 8127103424SAndreas Färber S390CPU *cpu = s390_env_get_cpu(env); 8227103424SAndreas Färber 830d404541SRichard Henderson qemu_log_mask(CPU_LOG_INT, "program interrupt at %#" PRIx64 "\n", 840d404541SRichard Henderson env->psw.addr); 85defb0e31SAlexander Graf 86defb0e31SAlexander Graf if (kvm_enabled()) { 87af2be207SJan Kiszka #ifdef CONFIG_KVM 8827103424SAndreas Färber kvm_s390_interrupt(cpu, KVM_S390_PROGRAM_INT, code); 89af2be207SJan Kiszka #endif 90defb0e31SAlexander Graf } else { 9127103424SAndreas Färber CPUState *cs = CPU(cpu); 9227103424SAndreas Färber 93defb0e31SAlexander Graf env->int_pgm_code = code; 94d5a103cdSRichard Henderson env->int_pgm_ilen = ilen; 9527103424SAndreas Färber cs->exception_index = EXCP_PGM; 965638d180SAndreas Färber cpu_loop_exit(cs); 97defb0e31SAlexander Graf } 98defb0e31SAlexander Graf } 99defb0e31SAlexander Graf 100defb0e31SAlexander Graf /* SCLP service call */ 101dc458df9SRichard Henderson uint32_t HELPER(servc)(CPUS390XState *env, uint64_t r1, uint64_t r2) 102defb0e31SAlexander Graf { 1036e252802SThomas Huth int r = sclp_service_call(env, r1, r2); 1049abf567dSChristian Borntraeger if (r < 0) { 1059abf567dSChristian Borntraeger program_interrupt(env, -r, 4); 106d5a43964SAlexander Graf return 0; 107d5a43964SAlexander Graf } 1089abf567dSChristian Borntraeger return r; 1099abf567dSChristian Borntraeger } 110defb0e31SAlexander Graf 111268846baSEugene (jno) Dvurechenski #ifndef CONFIG_USER_ONLY 112f0778475SChristian Borntraeger static void cpu_reset_all(void) 113f0778475SChristian Borntraeger { 114bdc44640SAndreas Färber CPUState *cs; 115f0778475SChristian Borntraeger S390CPUClass *scc; 116f0778475SChristian Borntraeger 117bdc44640SAndreas Färber CPU_FOREACH(cs) { 118bdc44640SAndreas Färber scc = S390_CPU_GET_CLASS(cs); 119bdc44640SAndreas Färber scc->cpu_reset(cs); 120f0778475SChristian Borntraeger } 121f0778475SChristian Borntraeger } 122f0778475SChristian Borntraeger 123d8b30c83SChristian Borntraeger static void cpu_full_reset_all(void) 124d8b30c83SChristian Borntraeger { 125d8b30c83SChristian Borntraeger CPUState *cpu; 126d8b30c83SChristian Borntraeger 127d8b30c83SChristian Borntraeger CPU_FOREACH(cpu) { 128d8b30c83SChristian Borntraeger cpu_reset(cpu); 129d8b30c83SChristian Borntraeger } 130d8b30c83SChristian Borntraeger } 131d8b30c83SChristian Borntraeger 132d8b30c83SChristian Borntraeger static int modified_clear_reset(S390CPU *cpu) 133d8b30c83SChristian Borntraeger { 134d8b30c83SChristian Borntraeger S390CPUClass *scc = S390_CPU_GET_CLASS(cpu); 135d8b30c83SChristian Borntraeger 136d8b30c83SChristian Borntraeger pause_all_vcpus(); 137d8b30c83SChristian Borntraeger cpu_synchronize_all_states(); 138d8b30c83SChristian Borntraeger cpu_full_reset_all(); 139d8b30c83SChristian Borntraeger io_subsystem_reset(); 140d8b30c83SChristian Borntraeger scc->load_normal(CPU(cpu)); 141d8b30c83SChristian Borntraeger cpu_synchronize_all_post_reset(); 142d8b30c83SChristian Borntraeger resume_all_vcpus(); 143d8b30c83SChristian Borntraeger return 0; 144d8b30c83SChristian Borntraeger } 145d8b30c83SChristian Borntraeger 146f0778475SChristian Borntraeger static int load_normal_reset(S390CPU *cpu) 147f0778475SChristian Borntraeger { 148f0778475SChristian Borntraeger S390CPUClass *scc = S390_CPU_GET_CLASS(cpu); 149f0778475SChristian Borntraeger 150f0778475SChristian Borntraeger pause_all_vcpus(); 151f0778475SChristian Borntraeger cpu_synchronize_all_states(); 152f0778475SChristian Borntraeger cpu_reset_all(); 153f0778475SChristian Borntraeger io_subsystem_reset(); 154f0778475SChristian Borntraeger scc->initial_cpu_reset(CPU(cpu)); 155f0778475SChristian Borntraeger scc->load_normal(CPU(cpu)); 156f0778475SChristian Borntraeger cpu_synchronize_all_post_reset(); 157f0778475SChristian Borntraeger resume_all_vcpus(); 158f0778475SChristian Borntraeger return 0; 159f0778475SChristian Borntraeger } 160f0778475SChristian Borntraeger 161268846baSEugene (jno) Dvurechenski #define DIAG_308_RC_NO_CONF 0x0102 162268846baSEugene (jno) Dvurechenski #define DIAG_308_RC_INVALID 0x0402 163268846baSEugene (jno) Dvurechenski void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3) 164268846baSEugene (jno) Dvurechenski { 165268846baSEugene (jno) Dvurechenski uint64_t addr = env->regs[r1]; 166268846baSEugene (jno) Dvurechenski uint64_t subcode = env->regs[r3]; 167268846baSEugene (jno) Dvurechenski 168268846baSEugene (jno) Dvurechenski if (env->psw.mask & PSW_MASK_PSTATE) { 169268846baSEugene (jno) Dvurechenski program_interrupt(env, PGM_PRIVILEGED, ILEN_LATER_INC); 170268846baSEugene (jno) Dvurechenski return; 171268846baSEugene (jno) Dvurechenski } 172268846baSEugene (jno) Dvurechenski 173268846baSEugene (jno) Dvurechenski if ((subcode & ~0x0ffffULL) || (subcode > 6)) { 174268846baSEugene (jno) Dvurechenski program_interrupt(env, PGM_SPECIFICATION, ILEN_LATER_INC); 175268846baSEugene (jno) Dvurechenski return; 176268846baSEugene (jno) Dvurechenski } 177268846baSEugene (jno) Dvurechenski 178268846baSEugene (jno) Dvurechenski switch (subcode) { 179d8b30c83SChristian Borntraeger case 0: 180d8b30c83SChristian Borntraeger modified_clear_reset(s390_env_get_cpu(env)); 181d8b30c83SChristian Borntraeger break; 182f0778475SChristian Borntraeger case 1: 183f0778475SChristian Borntraeger load_normal_reset(s390_env_get_cpu(env)); 184f0778475SChristian Borntraeger break; 185268846baSEugene (jno) Dvurechenski case 5: 186268846baSEugene (jno) Dvurechenski if ((r1 & 1) || (addr & 0x0fffULL)) { 187268846baSEugene (jno) Dvurechenski program_interrupt(env, PGM_SPECIFICATION, ILEN_LATER_INC); 188268846baSEugene (jno) Dvurechenski return; 189268846baSEugene (jno) Dvurechenski } 190268846baSEugene (jno) Dvurechenski env->regs[r1+1] = DIAG_308_RC_INVALID; 191268846baSEugene (jno) Dvurechenski return; 192268846baSEugene (jno) Dvurechenski case 6: 193268846baSEugene (jno) Dvurechenski if ((r1 & 1) || (addr & 0x0fffULL)) { 194268846baSEugene (jno) Dvurechenski program_interrupt(env, PGM_SPECIFICATION, ILEN_LATER_INC); 195268846baSEugene (jno) Dvurechenski return; 196268846baSEugene (jno) Dvurechenski } 197268846baSEugene (jno) Dvurechenski env->regs[r1+1] = DIAG_308_RC_NO_CONF; 198268846baSEugene (jno) Dvurechenski return; 199268846baSEugene (jno) Dvurechenski default: 200268846baSEugene (jno) Dvurechenski hw_error("Unhandled diag308 subcode %" PRIx64, subcode); 201268846baSEugene (jno) Dvurechenski break; 202268846baSEugene (jno) Dvurechenski } 203268846baSEugene (jno) Dvurechenski } 204268846baSEugene (jno) Dvurechenski #endif 205268846baSEugene (jno) Dvurechenski 206defb0e31SAlexander Graf /* DIAG */ 207089f5c06SBlue Swirl uint64_t HELPER(diag)(CPUS390XState *env, uint32_t num, uint64_t mem, 208089f5c06SBlue Swirl uint64_t code) 209defb0e31SAlexander Graf { 210defb0e31SAlexander Graf uint64_t r; 211defb0e31SAlexander Graf 212defb0e31SAlexander Graf switch (num) { 213defb0e31SAlexander Graf case 0x500: 214defb0e31SAlexander Graf /* KVM hypercall */ 21528e942f8SCornelia Huck r = s390_virtio_hypercall(env); 216defb0e31SAlexander Graf break; 217defb0e31SAlexander Graf case 0x44: 218defb0e31SAlexander Graf /* yield */ 219defb0e31SAlexander Graf r = 0; 220defb0e31SAlexander Graf break; 221defb0e31SAlexander Graf case 0x308: 222defb0e31SAlexander Graf /* ipl */ 223defb0e31SAlexander Graf r = 0; 224defb0e31SAlexander Graf break; 225defb0e31SAlexander Graf default: 226defb0e31SAlexander Graf r = -1; 227defb0e31SAlexander Graf break; 228defb0e31SAlexander Graf } 229defb0e31SAlexander Graf 230defb0e31SAlexander Graf if (r) { 231d5a103cdSRichard Henderson program_interrupt(env, PGM_OPERATION, ILEN_LATER_INC); 232defb0e31SAlexander Graf } 233defb0e31SAlexander Graf 234defb0e31SAlexander Graf return r; 235defb0e31SAlexander Graf } 236defb0e31SAlexander Graf 237defb0e31SAlexander Graf /* Set Prefix */ 238089f5c06SBlue Swirl void HELPER(spx)(CPUS390XState *env, uint64_t a1) 239defb0e31SAlexander Graf { 240e805a0d3SRichard Henderson uint32_t prefix = a1 & 0x7fffe000; 241e805a0d3SRichard Henderson env->psa = prefix; 242defb0e31SAlexander Graf qemu_log("prefix: %#x\n", prefix); 243defb0e31SAlexander Graf tlb_flush_page(env, 0); 244defb0e31SAlexander Graf tlb_flush_page(env, TARGET_PAGE_SIZE); 245defb0e31SAlexander Graf } 246defb0e31SAlexander Graf 247a4e3ad19SAndreas Färber static inline uint64_t clock_value(CPUS390XState *env) 248defb0e31SAlexander Graf { 249defb0e31SAlexander Graf uint64_t time; 250defb0e31SAlexander Graf 251defb0e31SAlexander Graf time = env->tod_offset + 252bc72ad67SAlex Bligh time2tod(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - env->tod_basetime); 253defb0e31SAlexander Graf 254defb0e31SAlexander Graf return time; 255defb0e31SAlexander Graf } 256defb0e31SAlexander Graf 257defb0e31SAlexander Graf /* Store Clock */ 258434c91a5SRichard Henderson uint64_t HELPER(stck)(CPUS390XState *env) 259defb0e31SAlexander Graf { 260434c91a5SRichard Henderson return clock_value(env); 261defb0e31SAlexander Graf } 262defb0e31SAlexander Graf 263defb0e31SAlexander Graf /* Set Clock Comparator */ 264dd3eb7b5SRichard Henderson void HELPER(sckc)(CPUS390XState *env, uint64_t time) 265defb0e31SAlexander Graf { 266defb0e31SAlexander Graf if (time == -1ULL) { 267defb0e31SAlexander Graf return; 268defb0e31SAlexander Graf } 269defb0e31SAlexander Graf 270defb0e31SAlexander Graf /* difference between now and then */ 271defb0e31SAlexander Graf time -= clock_value(env); 272defb0e31SAlexander Graf /* nanoseconds */ 273defb0e31SAlexander Graf time = (time * 125) >> 9; 274defb0e31SAlexander Graf 275bc72ad67SAlex Bligh timer_mod(env->tod_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + time); 276defb0e31SAlexander Graf } 277defb0e31SAlexander Graf 278defb0e31SAlexander Graf /* Store Clock Comparator */ 279dd3eb7b5SRichard Henderson uint64_t HELPER(stckc)(CPUS390XState *env) 280defb0e31SAlexander Graf { 281defb0e31SAlexander Graf /* XXX implement */ 282dd3eb7b5SRichard Henderson return 0; 283defb0e31SAlexander Graf } 284defb0e31SAlexander Graf 285defb0e31SAlexander Graf /* Set CPU Timer */ 286c4f0a863SRichard Henderson void HELPER(spt)(CPUS390XState *env, uint64_t time) 287defb0e31SAlexander Graf { 288defb0e31SAlexander Graf if (time == -1ULL) { 289defb0e31SAlexander Graf return; 290defb0e31SAlexander Graf } 291defb0e31SAlexander Graf 292defb0e31SAlexander Graf /* nanoseconds */ 293defb0e31SAlexander Graf time = (time * 125) >> 9; 294defb0e31SAlexander Graf 295bc72ad67SAlex Bligh timer_mod(env->cpu_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + time); 296defb0e31SAlexander Graf } 297defb0e31SAlexander Graf 298defb0e31SAlexander Graf /* Store CPU Timer */ 299c4f0a863SRichard Henderson uint64_t HELPER(stpt)(CPUS390XState *env) 300defb0e31SAlexander Graf { 301defb0e31SAlexander Graf /* XXX implement */ 302c4f0a863SRichard Henderson return 0; 303defb0e31SAlexander Graf } 304defb0e31SAlexander Graf 305defb0e31SAlexander Graf /* Store System Information */ 306d14b3e09SRichard Henderson uint32_t HELPER(stsi)(CPUS390XState *env, uint64_t a0, 307d14b3e09SRichard Henderson uint64_t r0, uint64_t r1) 308defb0e31SAlexander Graf { 309defb0e31SAlexander Graf int cc = 0; 310defb0e31SAlexander Graf int sel1, sel2; 311defb0e31SAlexander Graf 312defb0e31SAlexander Graf if ((r0 & STSI_LEVEL_MASK) <= STSI_LEVEL_3 && 313defb0e31SAlexander Graf ((r0 & STSI_R0_RESERVED_MASK) || (r1 & STSI_R1_RESERVED_MASK))) { 314defb0e31SAlexander Graf /* valid function code, invalid reserved bits */ 315defb0e31SAlexander Graf program_interrupt(env, PGM_SPECIFICATION, 2); 316defb0e31SAlexander Graf } 317defb0e31SAlexander Graf 318defb0e31SAlexander Graf sel1 = r0 & STSI_R0_SEL1_MASK; 319defb0e31SAlexander Graf sel2 = r1 & STSI_R1_SEL2_MASK; 320defb0e31SAlexander Graf 321defb0e31SAlexander Graf /* XXX: spec exception if sysib is not 4k-aligned */ 322defb0e31SAlexander Graf 323defb0e31SAlexander Graf switch (r0 & STSI_LEVEL_MASK) { 324defb0e31SAlexander Graf case STSI_LEVEL_1: 325defb0e31SAlexander Graf if ((sel1 == 1) && (sel2 == 1)) { 326defb0e31SAlexander Graf /* Basic Machine Configuration */ 327defb0e31SAlexander Graf struct sysib_111 sysib; 328defb0e31SAlexander Graf 329defb0e31SAlexander Graf memset(&sysib, 0, sizeof(sysib)); 330defb0e31SAlexander Graf ebcdic_put(sysib.manuf, "QEMU ", 16); 331defb0e31SAlexander Graf /* same as machine type number in STORE CPU ID */ 332defb0e31SAlexander Graf ebcdic_put(sysib.type, "QEMU", 4); 333defb0e31SAlexander Graf /* same as model number in STORE CPU ID */ 334defb0e31SAlexander Graf ebcdic_put(sysib.model, "QEMU ", 16); 335defb0e31SAlexander Graf ebcdic_put(sysib.sequence, "QEMU ", 16); 336defb0e31SAlexander Graf ebcdic_put(sysib.plant, "QEMU", 4); 337defb0e31SAlexander Graf cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1); 338defb0e31SAlexander Graf } else if ((sel1 == 2) && (sel2 == 1)) { 339defb0e31SAlexander Graf /* Basic Machine CPU */ 340defb0e31SAlexander Graf struct sysib_121 sysib; 341defb0e31SAlexander Graf 342defb0e31SAlexander Graf memset(&sysib, 0, sizeof(sysib)); 343defb0e31SAlexander Graf /* XXX make different for different CPUs? */ 344defb0e31SAlexander Graf ebcdic_put(sysib.sequence, "QEMUQEMUQEMUQEMU", 16); 345defb0e31SAlexander Graf ebcdic_put(sysib.plant, "QEMU", 4); 346defb0e31SAlexander Graf stw_p(&sysib.cpu_addr, env->cpu_num); 347defb0e31SAlexander Graf cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1); 348defb0e31SAlexander Graf } else if ((sel1 == 2) && (sel2 == 2)) { 349defb0e31SAlexander Graf /* Basic Machine CPUs */ 350defb0e31SAlexander Graf struct sysib_122 sysib; 351defb0e31SAlexander Graf 352defb0e31SAlexander Graf memset(&sysib, 0, sizeof(sysib)); 353defb0e31SAlexander Graf stl_p(&sysib.capability, 0x443afc29); 354defb0e31SAlexander Graf /* XXX change when SMP comes */ 355defb0e31SAlexander Graf stw_p(&sysib.total_cpus, 1); 356defb0e31SAlexander Graf stw_p(&sysib.active_cpus, 1); 357defb0e31SAlexander Graf stw_p(&sysib.standby_cpus, 0); 358defb0e31SAlexander Graf stw_p(&sysib.reserved_cpus, 0); 359defb0e31SAlexander Graf cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1); 360defb0e31SAlexander Graf } else { 361defb0e31SAlexander Graf cc = 3; 362defb0e31SAlexander Graf } 363defb0e31SAlexander Graf break; 364defb0e31SAlexander Graf case STSI_LEVEL_2: 365defb0e31SAlexander Graf { 366defb0e31SAlexander Graf if ((sel1 == 2) && (sel2 == 1)) { 367defb0e31SAlexander Graf /* LPAR CPU */ 368defb0e31SAlexander Graf struct sysib_221 sysib; 369defb0e31SAlexander Graf 370defb0e31SAlexander Graf memset(&sysib, 0, sizeof(sysib)); 371defb0e31SAlexander Graf /* XXX make different for different CPUs? */ 372defb0e31SAlexander Graf ebcdic_put(sysib.sequence, "QEMUQEMUQEMUQEMU", 16); 373defb0e31SAlexander Graf ebcdic_put(sysib.plant, "QEMU", 4); 374defb0e31SAlexander Graf stw_p(&sysib.cpu_addr, env->cpu_num); 375defb0e31SAlexander Graf stw_p(&sysib.cpu_id, 0); 376defb0e31SAlexander Graf cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1); 377defb0e31SAlexander Graf } else if ((sel1 == 2) && (sel2 == 2)) { 378defb0e31SAlexander Graf /* LPAR CPUs */ 379defb0e31SAlexander Graf struct sysib_222 sysib; 380defb0e31SAlexander Graf 381defb0e31SAlexander Graf memset(&sysib, 0, sizeof(sysib)); 382defb0e31SAlexander Graf stw_p(&sysib.lpar_num, 0); 383defb0e31SAlexander Graf sysib.lcpuc = 0; 384defb0e31SAlexander Graf /* XXX change when SMP comes */ 385defb0e31SAlexander Graf stw_p(&sysib.total_cpus, 1); 386defb0e31SAlexander Graf stw_p(&sysib.conf_cpus, 1); 387defb0e31SAlexander Graf stw_p(&sysib.standby_cpus, 0); 388defb0e31SAlexander Graf stw_p(&sysib.reserved_cpus, 0); 389defb0e31SAlexander Graf ebcdic_put(sysib.name, "QEMU ", 8); 390defb0e31SAlexander Graf stl_p(&sysib.caf, 1000); 391defb0e31SAlexander Graf stw_p(&sysib.dedicated_cpus, 0); 392defb0e31SAlexander Graf stw_p(&sysib.shared_cpus, 0); 393defb0e31SAlexander Graf cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1); 394defb0e31SAlexander Graf } else { 395defb0e31SAlexander Graf cc = 3; 396defb0e31SAlexander Graf } 397defb0e31SAlexander Graf break; 398defb0e31SAlexander Graf } 399defb0e31SAlexander Graf case STSI_LEVEL_3: 400defb0e31SAlexander Graf { 401defb0e31SAlexander Graf if ((sel1 == 2) && (sel2 == 2)) { 402defb0e31SAlexander Graf /* VM CPUs */ 403defb0e31SAlexander Graf struct sysib_322 sysib; 404defb0e31SAlexander Graf 405defb0e31SAlexander Graf memset(&sysib, 0, sizeof(sysib)); 406defb0e31SAlexander Graf sysib.count = 1; 407defb0e31SAlexander Graf /* XXX change when SMP comes */ 408defb0e31SAlexander Graf stw_p(&sysib.vm[0].total_cpus, 1); 409defb0e31SAlexander Graf stw_p(&sysib.vm[0].conf_cpus, 1); 410defb0e31SAlexander Graf stw_p(&sysib.vm[0].standby_cpus, 0); 411defb0e31SAlexander Graf stw_p(&sysib.vm[0].reserved_cpus, 0); 412defb0e31SAlexander Graf ebcdic_put(sysib.vm[0].name, "KVMguest", 8); 413defb0e31SAlexander Graf stl_p(&sysib.vm[0].caf, 1000); 414defb0e31SAlexander Graf ebcdic_put(sysib.vm[0].cpi, "KVM/Linux ", 16); 415defb0e31SAlexander Graf cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1); 416defb0e31SAlexander Graf } else { 417defb0e31SAlexander Graf cc = 3; 418defb0e31SAlexander Graf } 419defb0e31SAlexander Graf break; 420defb0e31SAlexander Graf } 421defb0e31SAlexander Graf case STSI_LEVEL_CURRENT: 422defb0e31SAlexander Graf env->regs[0] = STSI_LEVEL_3; 423defb0e31SAlexander Graf break; 424defb0e31SAlexander Graf default: 425defb0e31SAlexander Graf cc = 3; 426defb0e31SAlexander Graf break; 427defb0e31SAlexander Graf } 428defb0e31SAlexander Graf 429defb0e31SAlexander Graf return cc; 430defb0e31SAlexander Graf } 431defb0e31SAlexander Graf 432089f5c06SBlue Swirl uint32_t HELPER(sigp)(CPUS390XState *env, uint64_t order_code, uint32_t r1, 433089f5c06SBlue Swirl uint64_t cpu_addr) 434defb0e31SAlexander Graf { 435defb0e31SAlexander Graf int cc = 0; 436defb0e31SAlexander Graf 437defb0e31SAlexander Graf HELPER_LOG("%s: %016" PRIx64 " %08x %016" PRIx64 "\n", 43871e47088SBlue Swirl __func__, order_code, r1, cpu_addr); 439defb0e31SAlexander Graf 440defb0e31SAlexander Graf /* Remember: Use "R1 or R1 + 1, whichever is the odd-numbered register" 441defb0e31SAlexander Graf as parameter (input). Status (output) is always R1. */ 442defb0e31SAlexander Graf 443defb0e31SAlexander Graf switch (order_code) { 444defb0e31SAlexander Graf case SIGP_SET_ARCH: 445defb0e31SAlexander Graf /* switch arch */ 446defb0e31SAlexander Graf break; 447defb0e31SAlexander Graf case SIGP_SENSE: 448defb0e31SAlexander Graf /* enumerate CPU status */ 449defb0e31SAlexander Graf if (cpu_addr) { 450defb0e31SAlexander Graf /* XXX implement when SMP comes */ 451defb0e31SAlexander Graf return 3; 452defb0e31SAlexander Graf } 453defb0e31SAlexander Graf env->regs[r1] &= 0xffffffff00000000ULL; 454defb0e31SAlexander Graf cc = 1; 455defb0e31SAlexander Graf break; 4561864b94aSAlexander Graf #if !defined(CONFIG_USER_ONLY) 4571864b94aSAlexander Graf case SIGP_RESTART: 4581864b94aSAlexander Graf qemu_system_reset_request(); 4595638d180SAndreas Färber cpu_loop_exit(CPU(s390_env_get_cpu(env))); 4601864b94aSAlexander Graf break; 4611864b94aSAlexander Graf case SIGP_STOP: 4621864b94aSAlexander Graf qemu_system_shutdown_request(); 4635638d180SAndreas Färber cpu_loop_exit(CPU(s390_env_get_cpu(env))); 4641864b94aSAlexander Graf break; 4651864b94aSAlexander Graf #endif 466defb0e31SAlexander Graf default: 467defb0e31SAlexander Graf /* unknown sigp */ 468defb0e31SAlexander Graf fprintf(stderr, "XXX unknown sigp: 0x%" PRIx64 "\n", order_code); 469defb0e31SAlexander Graf cc = 3; 470defb0e31SAlexander Graf } 471defb0e31SAlexander Graf 472defb0e31SAlexander Graf return cc; 473defb0e31SAlexander Graf } 474defb0e31SAlexander Graf #endif 475