aboutsummaryrefslogtreecommitdiff
path: root/target/s390x/misc_helper.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2017-12-15 12:58:17 +0000
committerPeter Maydell <peter.maydell@linaro.org>2017-12-15 12:58:17 +0000
commita7cf5391a4a13eb63ec3b2da95cc33a762649d80 (patch)
tree18d65149abc30956ebde0e8bbf108f36e2673a75 /target/s390x/misc_helper.c
parent96a6298889d6de688bc076f5f223b73297f85462 (diff)
parentbb223055b9b327ec66e1f6d2fbaebaee0b8f3dbe (diff)
Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20171215-v2' into staging
s390x changes for 2.12: - Lots of tcg improvements: ccw hotplug is now working and we can run a Linux kernel built for z12 under tcg - zPCI improvements to get virtio-pci working - get rid of the cssid restrictions for virtual and non-virtual channel devices - we now support 8TB+ systems - 2.12 compat machine - fixes and cleanups # gpg: Signature made Fri 15 Dec 2017 10:57:01 GMT # gpg: using RSA key 0xDECF6B93C6F02FAF # gpg: Good signature from "Cornelia Huck <conny@cornelia-huck.de>" # gpg: aka "Cornelia Huck <huckc@linux.vnet.ibm.com>" # gpg: aka "Cornelia Huck <cornelia.huck@de.ibm.com>" # gpg: aka "Cornelia Huck <cohuck@kernel.org>" # gpg: aka "Cornelia Huck <cohuck@redhat.com>" # Primary key fingerprint: C3D0 D66D C362 4FF6 A8C0 18CE DECF 6B93 C6F0 2FAF * remotes/cohuck/tags/s390x-20171215-v2: (46 commits) s390-ccw-virtio: allow for systems larger that 7.999TB s390x: change the QEMU cpu model to a stripped down z12 s390x/tcg: we already implement the Set-Program-Parameter facility s390x/tcg: implement extract-CPU-time facility s390x/tcg: Implement SIGNAL ADAPTER instruction s390x/tcg: Implement STORE CHANNEL PATH STATUS s390x/tcg: wire up SET CHANNEL MONITOR s390x/tcg: wire up SET ADDRESS LIMIT s390x/tcg: implement Interlocked-Access Facility 2 s390x/tcg: ASI/ASGI/ALSI/ALSGI are atomic with Interlocked-acccess facility 1 s390x/tcg: wire up STORE CHANNEL REPORT WORD s390x/tcg: indicate value of TODPR in STCKE s390x/tcg: implement SET CLOCK PROGRAMMABLE FIELD s390x/tcg: fix and cleanup mcck injection s390x/kvm: factor out build_channel_report_mcic() into cpu.h s390x/css: attach css bridge s390x: deprecate s390-squash-mcss machine prop s390x/css: unrestrict cssids s390x/pci: search for subregion inside the BARs s390x/pci: move the memory region write from pcistg ... # Conflicts: # include/hw/compat.h Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target/s390x/misc_helper.c')
-rw-r--r--target/s390x/misc_helper.c111
1 files changed, 70 insertions, 41 deletions
diff --git a/target/s390x/misc_helper.c b/target/s390x/misc_helper.c
index d272851e1c..86da6aab7e 100644
--- a/target/s390x/misc_helper.c
+++ b/target/s390x/misc_helper.c
@@ -45,22 +45,6 @@
#define HELPER_LOG(x...)
#endif
-/* Raise an exception dynamically from a helper function. */
-void QEMU_NORETURN runtime_exception(CPUS390XState *env, int excp,
- uintptr_t retaddr)
-{
- CPUState *cs = CPU(s390_env_get_cpu(env));
-
- cs->exception_index = EXCP_PGM;
- env->int_pgm_code = excp;
- env->int_pgm_ilen = ILEN_AUTO;
-
- /* Use the (ultimate) callers address to find the insn that trapped. */
- cpu_restore_state(cs, retaddr);
-
- cpu_loop_exit(cs);
-}
-
/* Raise an exception statically from a TB. */
void HELPER(exception)(CPUS390XState *env, uint32_t excp)
{
@@ -71,6 +55,21 @@ void HELPER(exception)(CPUS390XState *env, uint32_t excp)
cpu_loop_exit(cs);
}
+/* Store CPU Timer (also used for EXTRACT CPU TIME) */
+uint64_t HELPER(stpt)(CPUS390XState *env)
+{
+#if defined(CONFIG_USER_ONLY)
+ /*
+ * Fake a descending CPU timer. We could get negative values here,
+ * but we don't care as it is up to the OS when to process that
+ * interrupt and reset to > 0.
+ */
+ return UINT64_MAX - (uint64_t)cpu_get_host_ticks();
+#else
+ return time2tod(env->cputm - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
+#endif
+}
+
#ifndef CONFIG_USER_ONLY
/* SCLP service call */
@@ -78,11 +77,10 @@ uint32_t HELPER(servc)(CPUS390XState *env, uint64_t r1, uint64_t r2)
{
qemu_mutex_lock_iothread();
int r = sclp_service_call(env, r1, r2);
+ qemu_mutex_unlock_iothread();
if (r < 0) {
- program_interrupt(env, -r, 4);
- r = 0;
+ s390_program_interrupt(env, -r, 4, GETPC());
}
- qemu_mutex_unlock_iothread();
return r;
}
@@ -104,7 +102,7 @@ void HELPER(diag)(CPUS390XState *env, uint32_t r1, uint32_t r3, uint32_t num)
case 0x308:
/* ipl */
qemu_mutex_lock_iothread();
- handle_diag_308(env, r1, r3);
+ handle_diag_308(env, r1, r3, GETPC());
qemu_mutex_unlock_iothread();
r = 0;
break;
@@ -118,7 +116,7 @@ void HELPER(diag)(CPUS390XState *env, uint32_t r1, uint32_t r3, uint32_t num)
}
if (r) {
- program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO);
+ s390_program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO, GETPC());
}
}
@@ -163,6 +161,17 @@ void HELPER(sckc)(CPUS390XState *env, uint64_t time)
timer_mod(env->tod_timer, env->tod_basetime + time);
}
+/* Set Tod Programmable Field */
+void HELPER(sckpf)(CPUS390XState *env, uint64_t r0)
+{
+ uint32_t val = r0;
+
+ if (val & 0xffff0000) {
+ s390_program_interrupt(env, PGM_SPECIFICATION, 2, GETPC());
+ }
+ env->todpr = val;
+}
+
/* Store Clock Comparator */
uint64_t HELPER(stckc)(CPUS390XState *env)
{
@@ -184,12 +193,6 @@ void HELPER(spt)(CPUS390XState *env, uint64_t time)
timer_mod(env->cpu_timer, env->cputm);
}
-/* Store CPU Timer */
-uint64_t HELPER(stpt)(CPUS390XState *env)
-{
- return time2tod(env->cputm - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
-}
-
/* Store System Information */
uint32_t HELPER(stsi)(CPUS390XState *env, uint64_t a0,
uint64_t r0, uint64_t r1)
@@ -201,7 +204,7 @@ uint32_t HELPER(stsi)(CPUS390XState *env, uint64_t a0,
if ((r0 & STSI_LEVEL_MASK) <= STSI_LEVEL_3 &&
((r0 & STSI_R0_RESERVED_MASK) || (r1 & STSI_R1_RESERVED_MASK))) {
/* valid function code, invalid reserved bits */
- program_interrupt(env, PGM_SPECIFICATION, 4);
+ s390_program_interrupt(env, PGM_SPECIFICATION, 4, GETPC());
}
sel1 = r0 & STSI_R0_SEL1_MASK;
@@ -339,7 +342,7 @@ void HELPER(xsch)(CPUS390XState *env, uint64_t r1)
{
S390CPU *cpu = s390_env_get_cpu(env);
qemu_mutex_lock_iothread();
- ioinst_handle_xsch(cpu, r1);
+ ioinst_handle_xsch(cpu, r1, GETPC());
qemu_mutex_unlock_iothread();
}
@@ -347,7 +350,7 @@ void HELPER(csch)(CPUS390XState *env, uint64_t r1)
{
S390CPU *cpu = s390_env_get_cpu(env);
qemu_mutex_lock_iothread();
- ioinst_handle_csch(cpu, r1);
+ ioinst_handle_csch(cpu, r1, GETPC());
qemu_mutex_unlock_iothread();
}
@@ -355,7 +358,7 @@ void HELPER(hsch)(CPUS390XState *env, uint64_t r1)
{
S390CPU *cpu = s390_env_get_cpu(env);
qemu_mutex_lock_iothread();
- ioinst_handle_hsch(cpu, r1);
+ ioinst_handle_hsch(cpu, r1, GETPC());
qemu_mutex_unlock_iothread();
}
@@ -363,7 +366,7 @@ void HELPER(msch)(CPUS390XState *env, uint64_t r1, uint64_t inst)
{
S390CPU *cpu = s390_env_get_cpu(env);
qemu_mutex_lock_iothread();
- ioinst_handle_msch(cpu, r1, inst >> 16);
+ ioinst_handle_msch(cpu, r1, inst >> 16, GETPC());
qemu_mutex_unlock_iothread();
}
@@ -371,7 +374,7 @@ void HELPER(rchp)(CPUS390XState *env, uint64_t r1)
{
S390CPU *cpu = s390_env_get_cpu(env);
qemu_mutex_lock_iothread();
- ioinst_handle_rchp(cpu, r1);
+ ioinst_handle_rchp(cpu, r1, GETPC());
qemu_mutex_unlock_iothread();
}
@@ -379,7 +382,25 @@ void HELPER(rsch)(CPUS390XState *env, uint64_t r1)
{
S390CPU *cpu = s390_env_get_cpu(env);
qemu_mutex_lock_iothread();
- ioinst_handle_rsch(cpu, r1);
+ ioinst_handle_rsch(cpu, r1, GETPC());
+ qemu_mutex_unlock_iothread();
+}
+
+void HELPER(sal)(CPUS390XState *env, uint64_t r1)
+{
+ S390CPU *cpu = s390_env_get_cpu(env);
+
+ qemu_mutex_lock_iothread();
+ ioinst_handle_sal(cpu, r1, GETPC());
+ qemu_mutex_unlock_iothread();
+}
+
+void HELPER(schm)(CPUS390XState *env, uint64_t r1, uint64_t r2, uint64_t inst)
+{
+ S390CPU *cpu = s390_env_get_cpu(env);
+
+ qemu_mutex_lock_iothread();
+ ioinst_handle_schm(cpu, r1, r2, inst >> 16, GETPC());
qemu_mutex_unlock_iothread();
}
@@ -387,7 +408,16 @@ void HELPER(ssch)(CPUS390XState *env, uint64_t r1, uint64_t inst)
{
S390CPU *cpu = s390_env_get_cpu(env);
qemu_mutex_lock_iothread();
- ioinst_handle_ssch(cpu, r1, inst >> 16);
+ ioinst_handle_ssch(cpu, r1, inst >> 16, GETPC());
+ qemu_mutex_unlock_iothread();
+}
+
+void HELPER(stcrw)(CPUS390XState *env, uint64_t inst)
+{
+ S390CPU *cpu = s390_env_get_cpu(env);
+
+ qemu_mutex_lock_iothread();
+ ioinst_handle_stcrw(cpu, inst >> 16, GETPC());
qemu_mutex_unlock_iothread();
}
@@ -395,7 +425,7 @@ void HELPER(stsch)(CPUS390XState *env, uint64_t r1, uint64_t inst)
{
S390CPU *cpu = s390_env_get_cpu(env);
qemu_mutex_lock_iothread();
- ioinst_handle_stsch(cpu, r1, inst >> 16);
+ ioinst_handle_stsch(cpu, r1, inst >> 16, GETPC());
qemu_mutex_unlock_iothread();
}
@@ -403,7 +433,7 @@ void HELPER(tsch)(CPUS390XState *env, uint64_t r1, uint64_t inst)
{
S390CPU *cpu = s390_env_get_cpu(env);
qemu_mutex_lock_iothread();
- ioinst_handle_tsch(cpu, r1, inst >> 16);
+ ioinst_handle_tsch(cpu, r1, inst >> 16, GETPC());
qemu_mutex_unlock_iothread();
}
@@ -411,7 +441,7 @@ void HELPER(chsc)(CPUS390XState *env, uint64_t inst)
{
S390CPU *cpu = s390_env_get_cpu(env);
qemu_mutex_lock_iothread();
- ioinst_handle_chsc(cpu, inst >> 16);
+ ioinst_handle_chsc(cpu, inst >> 16, GETPC());
qemu_mutex_unlock_iothread();
}
#endif
@@ -429,7 +459,7 @@ void HELPER(per_check_exception)(CPUS390XState *env)
* of EXECUTE, while per_address contains the target of EXECUTE.
*/
ilen = get_ilen(cpu_ldub_code(env, env->per_address));
- program_interrupt(env, PGM_PER, ilen);
+ s390_program_interrupt(env, PGM_PER, ilen, GETPC());
}
}
@@ -519,8 +549,7 @@ uint32_t HELPER(stfle)(CPUS390XState *env, uint64_t addr)
int i;
if (addr & 0x7) {
- cpu_restore_state(ENV_GET_CPU(env), ra);
- program_interrupt(env, PGM_SPECIFICATION, 4);
+ s390_program_interrupt(env, PGM_SPECIFICATION, 4, ra);
}
prepare_stfl();