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" 242ef6175aSRichard Henderson #include "exec/helper-proto.h" 25defb0e31SAlexander Graf #include <string.h> 269c17d615SPaolo Bonzini #include "sysemu/kvm.h" 271de7afc9SPaolo Bonzini #include "qemu/timer.h" 28df75a4e2SFan Zhang #include "exec/address-spaces.h" 29af2be207SJan Kiszka #ifdef CONFIG_KVM 30af2be207SJan Kiszka #include <linux/kvm.h> 31af2be207SJan Kiszka #endif 32f08b6170SPaolo Bonzini #include "exec/cpu_ldst.h" 3310ec5117SAlexander Graf 341864b94aSAlexander Graf #if !defined(CONFIG_USER_ONLY) 35f0778475SChristian Borntraeger #include "sysemu/cpus.h" 369c17d615SPaolo Bonzini #include "sysemu/sysemu.h" 3740fa5264SHeinz Graalfs #include "hw/s390x/ebcdic.h" 38df75a4e2SFan Zhang #include "hw/s390x/ipl.h" 3910ec5117SAlexander Graf #endif 40d5a43964SAlexander Graf 41defb0e31SAlexander Graf /* #define DEBUG_HELPER */ 42defb0e31SAlexander Graf #ifdef DEBUG_HELPER 43defb0e31SAlexander Graf #define HELPER_LOG(x...) qemu_log(x) 44defb0e31SAlexander Graf #else 45defb0e31SAlexander Graf #define HELPER_LOG(x...) 46defb0e31SAlexander Graf #endif 47defb0e31SAlexander Graf 48b4e2bd35SRichard Henderson /* Raise an exception dynamically from a helper function. */ 49b4e2bd35SRichard Henderson void QEMU_NORETURN runtime_exception(CPUS390XState *env, int excp, 50b4e2bd35SRichard Henderson uintptr_t retaddr) 51b4e2bd35SRichard Henderson { 5227103424SAndreas Färber CPUState *cs = CPU(s390_env_get_cpu(env)); 53b4e2bd35SRichard Henderson int t; 54b4e2bd35SRichard Henderson 5527103424SAndreas Färber cs->exception_index = EXCP_PGM; 56b4e2bd35SRichard Henderson env->int_pgm_code = excp; 57b4e2bd35SRichard Henderson 58b4e2bd35SRichard Henderson /* Use the (ultimate) callers address to find the insn that trapped. */ 593f38f309SAndreas Färber cpu_restore_state(cs, retaddr); 60b4e2bd35SRichard Henderson 61b4e2bd35SRichard Henderson /* Advance past the insn. */ 62b4e2bd35SRichard Henderson t = cpu_ldub_code(env, env->psw.addr); 63b4e2bd35SRichard Henderson env->int_pgm_ilen = t = get_ilen(t); 64b4e2bd35SRichard Henderson env->psw.addr += 2 * t; 65b4e2bd35SRichard Henderson 665638d180SAndreas Färber cpu_loop_exit(cs); 67b4e2bd35SRichard Henderson } 68b4e2bd35SRichard Henderson 69d5a103cdSRichard Henderson /* Raise an exception statically from a TB. */ 70089f5c06SBlue Swirl void HELPER(exception)(CPUS390XState *env, uint32_t excp) 71defb0e31SAlexander Graf { 7227103424SAndreas Färber CPUState *cs = CPU(s390_env_get_cpu(env)); 7327103424SAndreas Färber 7471e47088SBlue Swirl HELPER_LOG("%s: exception %d\n", __func__, excp); 7527103424SAndreas Färber cs->exception_index = excp; 765638d180SAndreas Färber cpu_loop_exit(cs); 77defb0e31SAlexander Graf } 78defb0e31SAlexander Graf 79defb0e31SAlexander Graf #ifndef CONFIG_USER_ONLY 80a158986dSStefan Weil 81d5a103cdSRichard Henderson void program_interrupt(CPUS390XState *env, uint32_t code, int ilen) 82defb0e31SAlexander Graf { 8327103424SAndreas Färber S390CPU *cpu = s390_env_get_cpu(env); 8427103424SAndreas Färber 850d404541SRichard Henderson qemu_log_mask(CPU_LOG_INT, "program interrupt at %#" PRIx64 "\n", 860d404541SRichard Henderson env->psw.addr); 87defb0e31SAlexander Graf 88defb0e31SAlexander Graf if (kvm_enabled()) { 89af2be207SJan Kiszka #ifdef CONFIG_KVM 90de13d216SCornelia Huck struct kvm_s390_irq irq = { 91de13d216SCornelia Huck .type = KVM_S390_PROGRAM_INT, 92de13d216SCornelia Huck .u.pgm.code = code, 93de13d216SCornelia Huck }; 94de13d216SCornelia Huck 95de13d216SCornelia Huck kvm_s390_vcpu_interrupt(cpu, &irq); 96af2be207SJan Kiszka #endif 97defb0e31SAlexander Graf } else { 9827103424SAndreas Färber CPUState *cs = CPU(cpu); 9927103424SAndreas Färber 100defb0e31SAlexander Graf env->int_pgm_code = code; 101d5a103cdSRichard Henderson env->int_pgm_ilen = ilen; 10227103424SAndreas Färber cs->exception_index = EXCP_PGM; 1035638d180SAndreas Färber cpu_loop_exit(cs); 104defb0e31SAlexander Graf } 105defb0e31SAlexander Graf } 106defb0e31SAlexander Graf 107defb0e31SAlexander Graf /* SCLP service call */ 108dc458df9SRichard Henderson uint32_t HELPER(servc)(CPUS390XState *env, uint64_t r1, uint64_t r2) 109defb0e31SAlexander Graf { 1106e252802SThomas Huth int r = sclp_service_call(env, r1, r2); 1119abf567dSChristian Borntraeger if (r < 0) { 1129abf567dSChristian Borntraeger program_interrupt(env, -r, 4); 113d5a43964SAlexander Graf return 0; 114d5a43964SAlexander Graf } 1159abf567dSChristian Borntraeger return r; 1169abf567dSChristian Borntraeger } 117defb0e31SAlexander Graf 118268846baSEugene (jno) Dvurechenski #ifndef CONFIG_USER_ONLY 119d8b30c83SChristian Borntraeger static int modified_clear_reset(S390CPU *cpu) 120d8b30c83SChristian Borntraeger { 121d8b30c83SChristian Borntraeger S390CPUClass *scc = S390_CPU_GET_CLASS(cpu); 12285ca3371SDavid Hildenbrand CPUState *t; 123d8b30c83SChristian Borntraeger 124d8b30c83SChristian Borntraeger pause_all_vcpus(); 125d8b30c83SChristian Borntraeger cpu_synchronize_all_states(); 12685ca3371SDavid Hildenbrand CPU_FOREACH(t) { 12785ca3371SDavid Hildenbrand run_on_cpu(t, s390_do_cpu_full_reset, t); 12885ca3371SDavid Hildenbrand } 1294cb88c3cSDominik Dingel cmma_reset(cpu); 130d8b30c83SChristian Borntraeger io_subsystem_reset(); 131d8b30c83SChristian Borntraeger scc->load_normal(CPU(cpu)); 132d8b30c83SChristian Borntraeger cpu_synchronize_all_post_reset(); 133d8b30c83SChristian Borntraeger resume_all_vcpus(); 134d8b30c83SChristian Borntraeger return 0; 135d8b30c83SChristian Borntraeger } 136d8b30c83SChristian Borntraeger 137f0778475SChristian Borntraeger static int load_normal_reset(S390CPU *cpu) 138f0778475SChristian Borntraeger { 139f0778475SChristian Borntraeger S390CPUClass *scc = S390_CPU_GET_CLASS(cpu); 14085ca3371SDavid Hildenbrand CPUState *t; 141f0778475SChristian Borntraeger 142f0778475SChristian Borntraeger pause_all_vcpus(); 143f0778475SChristian Borntraeger cpu_synchronize_all_states(); 14485ca3371SDavid Hildenbrand CPU_FOREACH(t) { 14585ca3371SDavid Hildenbrand run_on_cpu(t, s390_do_cpu_reset, t); 14685ca3371SDavid Hildenbrand } 1474cb88c3cSDominik Dingel cmma_reset(cpu); 148f0778475SChristian Borntraeger io_subsystem_reset(); 149f0778475SChristian Borntraeger scc->initial_cpu_reset(CPU(cpu)); 150f0778475SChristian Borntraeger scc->load_normal(CPU(cpu)); 151f0778475SChristian Borntraeger cpu_synchronize_all_post_reset(); 152f0778475SChristian Borntraeger resume_all_vcpus(); 153f0778475SChristian Borntraeger return 0; 154f0778475SChristian Borntraeger } 155f0778475SChristian Borntraeger 156df75a4e2SFan Zhang #define DIAG_308_RC_OK 0x0001 157268846baSEugene (jno) Dvurechenski #define DIAG_308_RC_NO_CONF 0x0102 158268846baSEugene (jno) Dvurechenski #define DIAG_308_RC_INVALID 0x0402 159df75a4e2SFan Zhang 160268846baSEugene (jno) Dvurechenski void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3) 161268846baSEugene (jno) Dvurechenski { 162268846baSEugene (jno) Dvurechenski uint64_t addr = env->regs[r1]; 163268846baSEugene (jno) Dvurechenski uint64_t subcode = env->regs[r3]; 164df75a4e2SFan Zhang IplParameterBlock *iplb; 165268846baSEugene (jno) Dvurechenski 166268846baSEugene (jno) Dvurechenski if (env->psw.mask & PSW_MASK_PSTATE) { 167268846baSEugene (jno) Dvurechenski program_interrupt(env, PGM_PRIVILEGED, ILEN_LATER_INC); 168268846baSEugene (jno) Dvurechenski return; 169268846baSEugene (jno) Dvurechenski } 170268846baSEugene (jno) Dvurechenski 171268846baSEugene (jno) Dvurechenski if ((subcode & ~0x0ffffULL) || (subcode > 6)) { 172268846baSEugene (jno) Dvurechenski program_interrupt(env, PGM_SPECIFICATION, ILEN_LATER_INC); 173268846baSEugene (jno) Dvurechenski return; 174268846baSEugene (jno) Dvurechenski } 175268846baSEugene (jno) Dvurechenski 176268846baSEugene (jno) Dvurechenski switch (subcode) { 177d8b30c83SChristian Borntraeger case 0: 178d8b30c83SChristian Borntraeger modified_clear_reset(s390_env_get_cpu(env)); 179d8b30c83SChristian Borntraeger break; 180f0778475SChristian Borntraeger case 1: 181f0778475SChristian Borntraeger load_normal_reset(s390_env_get_cpu(env)); 182f0778475SChristian Borntraeger break; 183268846baSEugene (jno) Dvurechenski case 5: 184268846baSEugene (jno) Dvurechenski if ((r1 & 1) || (addr & 0x0fffULL)) { 185268846baSEugene (jno) Dvurechenski program_interrupt(env, PGM_SPECIFICATION, ILEN_LATER_INC); 186268846baSEugene (jno) Dvurechenski return; 187268846baSEugene (jno) Dvurechenski } 188df75a4e2SFan Zhang if (!address_space_access_valid(&address_space_memory, addr, 189df75a4e2SFan Zhang sizeof(IplParameterBlock), false)) { 190df75a4e2SFan Zhang program_interrupt(env, PGM_ADDRESSING, ILEN_LATER_INC); 191df75a4e2SFan Zhang return; 192df75a4e2SFan Zhang } 193df75a4e2SFan Zhang iplb = g_malloc0(sizeof(struct IplParameterBlock)); 194df75a4e2SFan Zhang cpu_physical_memory_read(addr, iplb, sizeof(struct IplParameterBlock)); 195df75a4e2SFan Zhang if (!s390_ipl_update_diag308(iplb)) { 196df75a4e2SFan Zhang env->regs[r1 + 1] = DIAG_308_RC_OK; 197df75a4e2SFan Zhang } else { 198268846baSEugene (jno) Dvurechenski env->regs[r1 + 1] = DIAG_308_RC_INVALID; 199df75a4e2SFan Zhang } 200df75a4e2SFan Zhang g_free(iplb); 201268846baSEugene (jno) Dvurechenski return; 202268846baSEugene (jno) Dvurechenski case 6: 203268846baSEugene (jno) Dvurechenski if ((r1 & 1) || (addr & 0x0fffULL)) { 204268846baSEugene (jno) Dvurechenski program_interrupt(env, PGM_SPECIFICATION, ILEN_LATER_INC); 205268846baSEugene (jno) Dvurechenski return; 206268846baSEugene (jno) Dvurechenski } 207df75a4e2SFan Zhang if (!address_space_access_valid(&address_space_memory, addr, 208df75a4e2SFan Zhang sizeof(IplParameterBlock), true)) { 209df75a4e2SFan Zhang program_interrupt(env, PGM_ADDRESSING, ILEN_LATER_INC); 210df75a4e2SFan Zhang return; 211df75a4e2SFan Zhang } 212df75a4e2SFan Zhang iplb = s390_ipl_get_iplb(); 213df75a4e2SFan Zhang if (iplb) { 214df75a4e2SFan Zhang cpu_physical_memory_write(addr, iplb, 215df75a4e2SFan Zhang sizeof(struct IplParameterBlock)); 216df75a4e2SFan Zhang env->regs[r1 + 1] = DIAG_308_RC_OK; 217df75a4e2SFan Zhang } else { 218268846baSEugene (jno) Dvurechenski env->regs[r1 + 1] = DIAG_308_RC_NO_CONF; 219df75a4e2SFan Zhang } 220268846baSEugene (jno) Dvurechenski return; 221268846baSEugene (jno) Dvurechenski default: 222268846baSEugene (jno) Dvurechenski hw_error("Unhandled diag308 subcode %" PRIx64, subcode); 223268846baSEugene (jno) Dvurechenski break; 224268846baSEugene (jno) Dvurechenski } 225268846baSEugene (jno) Dvurechenski } 226268846baSEugene (jno) Dvurechenski #endif 227268846baSEugene (jno) Dvurechenski 228defb0e31SAlexander Graf /* DIAG */ 229089f5c06SBlue Swirl uint64_t HELPER(diag)(CPUS390XState *env, uint32_t num, uint64_t mem, 230089f5c06SBlue Swirl uint64_t code) 231defb0e31SAlexander Graf { 232defb0e31SAlexander Graf uint64_t r; 233defb0e31SAlexander Graf 234defb0e31SAlexander Graf switch (num) { 235defb0e31SAlexander Graf case 0x500: 236defb0e31SAlexander Graf /* KVM hypercall */ 23728e942f8SCornelia Huck r = s390_virtio_hypercall(env); 238defb0e31SAlexander Graf break; 239defb0e31SAlexander Graf case 0x44: 240defb0e31SAlexander Graf /* yield */ 241defb0e31SAlexander Graf r = 0; 242defb0e31SAlexander Graf break; 243defb0e31SAlexander Graf case 0x308: 244defb0e31SAlexander Graf /* ipl */ 245defb0e31SAlexander Graf r = 0; 246defb0e31SAlexander Graf break; 247defb0e31SAlexander Graf default: 248defb0e31SAlexander Graf r = -1; 249defb0e31SAlexander Graf break; 250defb0e31SAlexander Graf } 251defb0e31SAlexander Graf 252defb0e31SAlexander Graf if (r) { 253d5a103cdSRichard Henderson program_interrupt(env, PGM_OPERATION, ILEN_LATER_INC); 254defb0e31SAlexander Graf } 255defb0e31SAlexander Graf 256defb0e31SAlexander Graf return r; 257defb0e31SAlexander Graf } 258defb0e31SAlexander Graf 259defb0e31SAlexander Graf /* Set Prefix */ 260089f5c06SBlue Swirl void HELPER(spx)(CPUS390XState *env, uint64_t a1) 261defb0e31SAlexander Graf { 26231b030d4SAndreas Färber CPUState *cs = CPU(s390_env_get_cpu(env)); 263e805a0d3SRichard Henderson uint32_t prefix = a1 & 0x7fffe000; 26431b030d4SAndreas Färber 265e805a0d3SRichard Henderson env->psa = prefix; 266defb0e31SAlexander Graf qemu_log("prefix: %#x\n", prefix); 26731b030d4SAndreas Färber tlb_flush_page(cs, 0); 26831b030d4SAndreas Färber tlb_flush_page(cs, TARGET_PAGE_SIZE); 269defb0e31SAlexander Graf } 270defb0e31SAlexander Graf 271a4e3ad19SAndreas Färber static inline uint64_t clock_value(CPUS390XState *env) 272defb0e31SAlexander Graf { 273defb0e31SAlexander Graf uint64_t time; 274defb0e31SAlexander Graf 275defb0e31SAlexander Graf time = env->tod_offset + 276bc72ad67SAlex Bligh time2tod(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - env->tod_basetime); 277defb0e31SAlexander Graf 278defb0e31SAlexander Graf return time; 279defb0e31SAlexander Graf } 280defb0e31SAlexander Graf 281defb0e31SAlexander Graf /* Store Clock */ 282434c91a5SRichard Henderson uint64_t HELPER(stck)(CPUS390XState *env) 283defb0e31SAlexander Graf { 284434c91a5SRichard Henderson return clock_value(env); 285defb0e31SAlexander Graf } 286defb0e31SAlexander Graf 287defb0e31SAlexander Graf /* Set Clock Comparator */ 288dd3eb7b5SRichard Henderson void HELPER(sckc)(CPUS390XState *env, uint64_t time) 289defb0e31SAlexander Graf { 290defb0e31SAlexander Graf if (time == -1ULL) { 291defb0e31SAlexander Graf return; 292defb0e31SAlexander Graf } 293defb0e31SAlexander Graf 294defb0e31SAlexander Graf /* difference between now and then */ 295defb0e31SAlexander Graf time -= clock_value(env); 296defb0e31SAlexander Graf /* nanoseconds */ 297defb0e31SAlexander Graf time = (time * 125) >> 9; 298defb0e31SAlexander Graf 299bc72ad67SAlex Bligh timer_mod(env->tod_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + time); 300defb0e31SAlexander Graf } 301defb0e31SAlexander Graf 302defb0e31SAlexander Graf /* Store Clock Comparator */ 303dd3eb7b5SRichard Henderson uint64_t HELPER(stckc)(CPUS390XState *env) 304defb0e31SAlexander Graf { 305defb0e31SAlexander Graf /* XXX implement */ 306dd3eb7b5SRichard Henderson return 0; 307defb0e31SAlexander Graf } 308defb0e31SAlexander Graf 309defb0e31SAlexander Graf /* Set CPU Timer */ 310c4f0a863SRichard Henderson void HELPER(spt)(CPUS390XState *env, uint64_t time) 311defb0e31SAlexander Graf { 312defb0e31SAlexander Graf if (time == -1ULL) { 313defb0e31SAlexander Graf return; 314defb0e31SAlexander Graf } 315defb0e31SAlexander Graf 316defb0e31SAlexander Graf /* nanoseconds */ 317defb0e31SAlexander Graf time = (time * 125) >> 9; 318defb0e31SAlexander Graf 319bc72ad67SAlex Bligh timer_mod(env->cpu_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + time); 320defb0e31SAlexander Graf } 321defb0e31SAlexander Graf 322defb0e31SAlexander Graf /* Store CPU Timer */ 323c4f0a863SRichard Henderson uint64_t HELPER(stpt)(CPUS390XState *env) 324defb0e31SAlexander Graf { 325defb0e31SAlexander Graf /* XXX implement */ 326c4f0a863SRichard Henderson return 0; 327defb0e31SAlexander Graf } 328defb0e31SAlexander Graf 329defb0e31SAlexander Graf /* Store System Information */ 330d14b3e09SRichard Henderson uint32_t HELPER(stsi)(CPUS390XState *env, uint64_t a0, 331d14b3e09SRichard Henderson uint64_t r0, uint64_t r1) 332defb0e31SAlexander Graf { 333defb0e31SAlexander Graf int cc = 0; 334defb0e31SAlexander Graf int sel1, sel2; 335defb0e31SAlexander Graf 336defb0e31SAlexander Graf if ((r0 & STSI_LEVEL_MASK) <= STSI_LEVEL_3 && 337defb0e31SAlexander Graf ((r0 & STSI_R0_RESERVED_MASK) || (r1 & STSI_R1_RESERVED_MASK))) { 338defb0e31SAlexander Graf /* valid function code, invalid reserved bits */ 339defb0e31SAlexander Graf program_interrupt(env, PGM_SPECIFICATION, 2); 340defb0e31SAlexander Graf } 341defb0e31SAlexander Graf 342defb0e31SAlexander Graf sel1 = r0 & STSI_R0_SEL1_MASK; 343defb0e31SAlexander Graf sel2 = r1 & STSI_R1_SEL2_MASK; 344defb0e31SAlexander Graf 345defb0e31SAlexander Graf /* XXX: spec exception if sysib is not 4k-aligned */ 346defb0e31SAlexander Graf 347defb0e31SAlexander Graf switch (r0 & STSI_LEVEL_MASK) { 348defb0e31SAlexander Graf case STSI_LEVEL_1: 349defb0e31SAlexander Graf if ((sel1 == 1) && (sel2 == 1)) { 350defb0e31SAlexander Graf /* Basic Machine Configuration */ 351defb0e31SAlexander Graf struct sysib_111 sysib; 352defb0e31SAlexander Graf 353defb0e31SAlexander Graf memset(&sysib, 0, sizeof(sysib)); 354defb0e31SAlexander Graf ebcdic_put(sysib.manuf, "QEMU ", 16); 355defb0e31SAlexander Graf /* same as machine type number in STORE CPU ID */ 356defb0e31SAlexander Graf ebcdic_put(sysib.type, "QEMU", 4); 357defb0e31SAlexander Graf /* same as model number in STORE CPU ID */ 358defb0e31SAlexander Graf ebcdic_put(sysib.model, "QEMU ", 16); 359defb0e31SAlexander Graf ebcdic_put(sysib.sequence, "QEMU ", 16); 360defb0e31SAlexander Graf ebcdic_put(sysib.plant, "QEMU", 4); 361eb6282f2SStefan Weil cpu_physical_memory_write(a0, &sysib, sizeof(sysib)); 362defb0e31SAlexander Graf } else if ((sel1 == 2) && (sel2 == 1)) { 363defb0e31SAlexander Graf /* Basic Machine CPU */ 364defb0e31SAlexander Graf struct sysib_121 sysib; 365defb0e31SAlexander Graf 366defb0e31SAlexander Graf memset(&sysib, 0, sizeof(sysib)); 367defb0e31SAlexander Graf /* XXX make different for different CPUs? */ 368defb0e31SAlexander Graf ebcdic_put(sysib.sequence, "QEMUQEMUQEMUQEMU", 16); 369defb0e31SAlexander Graf ebcdic_put(sysib.plant, "QEMU", 4); 370defb0e31SAlexander Graf stw_p(&sysib.cpu_addr, env->cpu_num); 371eb6282f2SStefan Weil cpu_physical_memory_write(a0, &sysib, sizeof(sysib)); 372defb0e31SAlexander Graf } else if ((sel1 == 2) && (sel2 == 2)) { 373defb0e31SAlexander Graf /* Basic Machine CPUs */ 374defb0e31SAlexander Graf struct sysib_122 sysib; 375defb0e31SAlexander Graf 376defb0e31SAlexander Graf memset(&sysib, 0, sizeof(sysib)); 377defb0e31SAlexander Graf stl_p(&sysib.capability, 0x443afc29); 378defb0e31SAlexander Graf /* XXX change when SMP comes */ 379defb0e31SAlexander Graf stw_p(&sysib.total_cpus, 1); 380defb0e31SAlexander Graf stw_p(&sysib.active_cpus, 1); 381defb0e31SAlexander Graf stw_p(&sysib.standby_cpus, 0); 382defb0e31SAlexander Graf stw_p(&sysib.reserved_cpus, 0); 383eb6282f2SStefan Weil cpu_physical_memory_write(a0, &sysib, sizeof(sysib)); 384defb0e31SAlexander Graf } else { 385defb0e31SAlexander Graf cc = 3; 386defb0e31SAlexander Graf } 387defb0e31SAlexander Graf break; 388defb0e31SAlexander Graf case STSI_LEVEL_2: 389defb0e31SAlexander Graf { 390defb0e31SAlexander Graf if ((sel1 == 2) && (sel2 == 1)) { 391defb0e31SAlexander Graf /* LPAR CPU */ 392defb0e31SAlexander Graf struct sysib_221 sysib; 393defb0e31SAlexander Graf 394defb0e31SAlexander Graf memset(&sysib, 0, sizeof(sysib)); 395defb0e31SAlexander Graf /* XXX make different for different CPUs? */ 396defb0e31SAlexander Graf ebcdic_put(sysib.sequence, "QEMUQEMUQEMUQEMU", 16); 397defb0e31SAlexander Graf ebcdic_put(sysib.plant, "QEMU", 4); 398defb0e31SAlexander Graf stw_p(&sysib.cpu_addr, env->cpu_num); 399defb0e31SAlexander Graf stw_p(&sysib.cpu_id, 0); 400eb6282f2SStefan Weil cpu_physical_memory_write(a0, &sysib, sizeof(sysib)); 401defb0e31SAlexander Graf } else if ((sel1 == 2) && (sel2 == 2)) { 402defb0e31SAlexander Graf /* LPAR CPUs */ 403defb0e31SAlexander Graf struct sysib_222 sysib; 404defb0e31SAlexander Graf 405defb0e31SAlexander Graf memset(&sysib, 0, sizeof(sysib)); 406defb0e31SAlexander Graf stw_p(&sysib.lpar_num, 0); 407defb0e31SAlexander Graf sysib.lcpuc = 0; 408defb0e31SAlexander Graf /* XXX change when SMP comes */ 409defb0e31SAlexander Graf stw_p(&sysib.total_cpus, 1); 410defb0e31SAlexander Graf stw_p(&sysib.conf_cpus, 1); 411defb0e31SAlexander Graf stw_p(&sysib.standby_cpus, 0); 412defb0e31SAlexander Graf stw_p(&sysib.reserved_cpus, 0); 413defb0e31SAlexander Graf ebcdic_put(sysib.name, "QEMU ", 8); 414defb0e31SAlexander Graf stl_p(&sysib.caf, 1000); 415defb0e31SAlexander Graf stw_p(&sysib.dedicated_cpus, 0); 416defb0e31SAlexander Graf stw_p(&sysib.shared_cpus, 0); 417eb6282f2SStefan Weil cpu_physical_memory_write(a0, &sysib, sizeof(sysib)); 418defb0e31SAlexander Graf } else { 419defb0e31SAlexander Graf cc = 3; 420defb0e31SAlexander Graf } 421defb0e31SAlexander Graf break; 422defb0e31SAlexander Graf } 423defb0e31SAlexander Graf case STSI_LEVEL_3: 424defb0e31SAlexander Graf { 425defb0e31SAlexander Graf if ((sel1 == 2) && (sel2 == 2)) { 426defb0e31SAlexander Graf /* VM CPUs */ 427defb0e31SAlexander Graf struct sysib_322 sysib; 428defb0e31SAlexander Graf 429defb0e31SAlexander Graf memset(&sysib, 0, sizeof(sysib)); 430defb0e31SAlexander Graf sysib.count = 1; 431defb0e31SAlexander Graf /* XXX change when SMP comes */ 432defb0e31SAlexander Graf stw_p(&sysib.vm[0].total_cpus, 1); 433defb0e31SAlexander Graf stw_p(&sysib.vm[0].conf_cpus, 1); 434defb0e31SAlexander Graf stw_p(&sysib.vm[0].standby_cpus, 0); 435defb0e31SAlexander Graf stw_p(&sysib.vm[0].reserved_cpus, 0); 436defb0e31SAlexander Graf ebcdic_put(sysib.vm[0].name, "KVMguest", 8); 437defb0e31SAlexander Graf stl_p(&sysib.vm[0].caf, 1000); 438defb0e31SAlexander Graf ebcdic_put(sysib.vm[0].cpi, "KVM/Linux ", 16); 439eb6282f2SStefan Weil cpu_physical_memory_write(a0, &sysib, sizeof(sysib)); 440defb0e31SAlexander Graf } else { 441defb0e31SAlexander Graf cc = 3; 442defb0e31SAlexander Graf } 443defb0e31SAlexander Graf break; 444defb0e31SAlexander Graf } 445defb0e31SAlexander Graf case STSI_LEVEL_CURRENT: 446defb0e31SAlexander Graf env->regs[0] = STSI_LEVEL_3; 447defb0e31SAlexander Graf break; 448defb0e31SAlexander Graf default: 449defb0e31SAlexander Graf cc = 3; 450defb0e31SAlexander Graf break; 451defb0e31SAlexander Graf } 452defb0e31SAlexander Graf 453defb0e31SAlexander Graf return cc; 454defb0e31SAlexander Graf } 455defb0e31SAlexander Graf 456089f5c06SBlue Swirl uint32_t HELPER(sigp)(CPUS390XState *env, uint64_t order_code, uint32_t r1, 457089f5c06SBlue Swirl uint64_t cpu_addr) 458defb0e31SAlexander Graf { 459defb0e31SAlexander Graf int cc = 0; 460defb0e31SAlexander Graf 461defb0e31SAlexander Graf HELPER_LOG("%s: %016" PRIx64 " %08x %016" PRIx64 "\n", 46271e47088SBlue Swirl __func__, order_code, r1, cpu_addr); 463defb0e31SAlexander Graf 464defb0e31SAlexander Graf /* Remember: Use "R1 or R1 + 1, whichever is the odd-numbered register" 465defb0e31SAlexander Graf as parameter (input). Status (output) is always R1. */ 466defb0e31SAlexander Graf 467defb0e31SAlexander Graf switch (order_code) { 468defb0e31SAlexander Graf case SIGP_SET_ARCH: 469defb0e31SAlexander Graf /* switch arch */ 470defb0e31SAlexander Graf break; 471defb0e31SAlexander Graf case SIGP_SENSE: 472defb0e31SAlexander Graf /* enumerate CPU status */ 473defb0e31SAlexander Graf if (cpu_addr) { 474defb0e31SAlexander Graf /* XXX implement when SMP comes */ 475defb0e31SAlexander Graf return 3; 476defb0e31SAlexander Graf } 477defb0e31SAlexander Graf env->regs[r1] &= 0xffffffff00000000ULL; 478defb0e31SAlexander Graf cc = 1; 479defb0e31SAlexander Graf break; 4801864b94aSAlexander Graf #if !defined(CONFIG_USER_ONLY) 4811864b94aSAlexander Graf case SIGP_RESTART: 4821864b94aSAlexander Graf qemu_system_reset_request(); 4835638d180SAndreas Färber cpu_loop_exit(CPU(s390_env_get_cpu(env))); 4841864b94aSAlexander Graf break; 4851864b94aSAlexander Graf case SIGP_STOP: 4861864b94aSAlexander Graf qemu_system_shutdown_request(); 4875638d180SAndreas Färber cpu_loop_exit(CPU(s390_env_get_cpu(env))); 4881864b94aSAlexander Graf break; 4891864b94aSAlexander Graf #endif 490defb0e31SAlexander Graf default: 491defb0e31SAlexander Graf /* unknown sigp */ 492defb0e31SAlexander Graf fprintf(stderr, "XXX unknown sigp: 0x%" PRIx64 "\n", order_code); 493defb0e31SAlexander Graf cc = 3; 494defb0e31SAlexander Graf } 495defb0e31SAlexander Graf 496defb0e31SAlexander Graf return cc; 497defb0e31SAlexander Graf } 498defb0e31SAlexander Graf #endif 499