aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/s390x/sclp.c9
-rw-r--r--target-s390x/cpu.h2
-rw-r--r--target-s390x/kvm.c6
-rw-r--r--target-s390x/misc_helper.c2
4 files changed, 10 insertions, 9 deletions
diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c
index 6134d4f904..98809777c8 100644
--- a/hw/s390x/sclp.c
+++ b/hw/s390x/sclp.c
@@ -107,7 +107,7 @@ static void sclp_execute(SCCB *sccb, uint32_t code)
}
}
-int sclp_service_call(uint64_t sccb, uint32_t code)
+int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code)
{
int r = 0;
SCCB work_sccb;
@@ -115,11 +115,16 @@ int sclp_service_call(uint64_t sccb, uint32_t code)
hwaddr sccb_len = sizeof(SCCB);
/* first some basic checks on program checks */
+ if (env->psw.mask & PSW_MASK_PSTATE) {
+ r = -PGM_PRIVILEGED;
+ goto out;
+ }
if (cpu_physical_memory_is_io(sccb)) {
r = -PGM_ADDRESSING;
goto out;
}
- if (sccb & ~0x7ffffff8ul) {
+ if ((sccb & ~0x1fffUL) == 0 || (sccb & ~0x1fffUL) == env->psa
+ || (sccb & ~0x7ffffff8UL) != 0) {
r = -PGM_SPECIFICATION;
goto out;
}
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 373c1151c1..96738384c7 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -963,7 +963,7 @@ struct sysib_322 {
void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr);
int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc,
target_ulong *raddr, int *flags);
-int sclp_service_call(uint64_t sccb, uint32_t code);
+int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code);
uint32_t calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src, uint64_t dst,
uint64_t vr);
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 9e1083e9d8..e7b3b1375c 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -445,14 +445,10 @@ static int kvm_sclp_service_call(S390CPU *cpu, struct kvm_run *run,
int r = 0;
cpu_synchronize_state(CPU(cpu));
- if (env->psw.mask & PSW_MASK_PSTATE) {
- enter_pgmcheck(cpu, PGM_PRIVILEGED);
- return 0;
- }
sccb = env->regs[ipbh0 & 0xf];
code = env->regs[(ipbh0 & 0xf0) >> 4];
- r = sclp_service_call(sccb, code);
+ r = sclp_service_call(env, sccb, code);
if (r < 0) {
enter_pgmcheck(cpu, -r);
}
diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c
index 10d04252d5..728456f295 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -93,7 +93,7 @@ void program_interrupt(CPUS390XState *env, uint32_t code, int ilen)
/* SCLP service call */
uint32_t HELPER(servc)(CPUS390XState *env, uint64_t r1, uint64_t r2)
{
- int r = sclp_service_call(r1, r2);
+ int r = sclp_service_call(env, r1, r2);
if (r < 0) {
program_interrupt(env, -r, 4);
return 0;