s390x/sclp: Add missing checks to SCLP handler
authorThomas Huth <thuth@linux.vnet.ibm.com>
Mon, 13 Jan 2014 11:55:55 +0000 (12:55 +0100)
committerChristian Borntraeger <borntraeger@de.ibm.com>
Thu, 27 Feb 2014 08:51:25 +0000 (09:51 +0100)
If the 51 most significant bits of the SCCB address are zero or equal to
the prefix, we should throw an specification exception, too.
Also moved the check for privileged mode to sclp_service_call() to have
all program checks in one place now.

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
hw/s390x/sclp.c
target-s390x/cpu.h
target-s390x/kvm.c
target-s390x/misc_helper.c

index 6134d4f9040931828822a1124a0235f229509890..98809777c8c06c983575eb75553cacf6c5443663 100644 (file)
@@ -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;
     }
index 373c1151c1d4098deff9e11fe6c0daba6a9e65e0..96738384c781c1792425fd0afd6ae98763b94f20 100644 (file)
@@ -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);
 
index 9e1083e9d8a0b8c58f480dc21c684dfc16b865da..e7b3b1375ca92bb43c8dd222202a2e15c30c641d 100644 (file)
@@ -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);
     }
index 10d04252d58c9c54b3acaf8e77343a6aecbc2d91..728456f2954f64cb66d2a81c92bdb560a239e7fd 100644 (file)
@@ -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;