]> Git Repo - qemu.git/commitdiff
s390: Fix error handling and condition code of service call
authorChristian Borntraeger <[email protected]>
Mon, 23 Jul 2012 21:37:04 +0000 (21:37 +0000)
committerAlexander Graf <[email protected]>
Wed, 15 Aug 2012 15:47:09 +0000 (17:47 +0200)
Invalid sccb addresses will cause specification or addressing exception.
Lets add those checks. Furthermore, the good case (cc=0) was incorrect
for KVM, we did not set the CC at all. We now use return codes < 0
as program checks and return codes > 0 as condition code values.

Signed-off-by: Christian Borntraeger <[email protected]>
Signed-off-by: Alexander Graf <[email protected]>
target-s390x/kvm.c
target-s390x/op_helper.c

index 47008c24f2a4c3f05a9a2f66c905860193e6d719..07edf93690190cf4d6131b520574b95b55bbd33d 100644 (file)
@@ -273,9 +273,10 @@ static int kvm_sclp_service_call(CPUS390XState *env, struct kvm_run *run,
     code = env->regs[(ipbh0 & 0xf0) >> 4];
 
     r = sclp_service_call(env, sccb, code);
-    if (r) {
-        setcc(env, 3);
+    if (r < 0) {
+        enter_pgmcheck(env, -r);
     }
+    setcc(env, r);
 
     return 0;
 }
index 7b7247316ec06367be83a9f5512eec9c5636d880..91dd8dc3fb9319e15d307772f89b73644d463a0e 100644 (file)
@@ -19,6 +19,8 @@
  */
 
 #include "cpu.h"
+#include "memory.h"
+#include "cputlb.h"
 #include "dyngen-exec.h"
 #include "host-utils.h"
 #include "helper.h"
@@ -2366,6 +2368,9 @@ static void ext_interrupt(CPUS390XState *env, int type, uint32_t param,
     cpu_inject_ext(env, type, param, param64);
 }
 
+/*
+ * ret < 0 indicates program check, ret = 0,1,2,3 -> cc
+ */
 int sclp_service_call(CPUS390XState *env, uint32_t sccb, uint64_t code)
 {
     int r = 0;
@@ -2375,10 +2380,12 @@ int sclp_service_call(CPUS390XState *env, uint32_t sccb, uint64_t code)
     printf("sclp(0x%x, 0x%" PRIx64 ")\n", sccb, code);
 #endif
 
+    /* basic checks */
+    if (!memory_region_is_ram(phys_page_find(sccb >> TARGET_PAGE_BITS)->mr)) {
+        return -PGM_ADDRESSING;
+    }
     if (sccb & ~0x7ffffff8ul) {
-        fprintf(stderr, "KVM: invalid sccb address 0x%x\n", sccb);
-        r = -1;
-        goto out;
+        return -PGM_SPECIFICATION;
     }
 
     switch(code) {
@@ -2405,22 +2412,24 @@ int sclp_service_call(CPUS390XState *env, uint32_t sccb, uint64_t code)
 #ifdef DEBUG_HELPER
             printf("KVM: invalid sclp call 0x%x / 0x%" PRIx64 "x\n", sccb, code);
 #endif
-            r = -1;
+            r = 3;
             break;
     }
 
-out:
     return r;
 }
 
 /* SCLP service call */
 uint32_t HELPER(servc)(uint32_t r1, uint64_t r2)
 {
-    if (sclp_service_call(env, r1, r2)) {
-        return 3;
-    }
+    int r;
 
-    return 0;
+    r = sclp_service_call(env, r1, r2);
+    if (r < 0) {
+        program_interrupt(env, -r, 4);
+        return 0;
+    }
+    return r;
 }
 
 /* DIAG */
This page took 0.032778 seconds and 4 git commands to generate.