diff mbox

[PULL,17/29] s390x/kvm: Add function for injecting pgm access exceptions

Message ID 1424290943-22480-18-git-send-email-borntraeger@de.ibm.com
State New
Headers show

Commit Message

Christian Borntraeger Feb. 18, 2015, 8:22 p.m. UTC
From: Thomas Huth <thuth@linux.vnet.ibm.com>

Program access exceptions are defined to deliver a translation exception
code in the low-core. Add a function trigger_access_exception() that
generates the proper program interrupt on both KVM and non-KVM systems
and switch the existing code to use it.

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
---
 target-s390x/cpu.h        |  5 +++++
 target-s390x/kvm.c        | 12 ++++++++++++
 target-s390x/mmu_helper.c | 22 ++++++++++++++++------
 3 files changed, 33 insertions(+), 6 deletions(-)
diff mbox

Patch

diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index c24ca5f..f8cea30 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -397,6 +397,7 @@  void kvm_s390_service_interrupt(uint32_t parm);
 void kvm_s390_vcpu_interrupt(S390CPU *cpu, struct kvm_s390_irq *irq);
 void kvm_s390_floating_interrupt(struct kvm_s390_irq *irq);
 int kvm_s390_inject_flic(struct kvm_s390_irq *irq);
+void kvm_s390_access_exception(S390CPU *cpu, uint16_t code, uint64_t te_code);
 #else
 static inline void kvm_s390_virtio_irq(int config_change, uint64_t token)
 {
@@ -404,6 +405,10 @@  static inline void kvm_s390_virtio_irq(int config_change, uint64_t token)
 static inline void kvm_s390_service_interrupt(uint32_t parm)
 {
 }
+static inline void kvm_s390_access_exception(S390CPU *cpu, uint16_t code,
+                                             uint64_t te_code)
+{
+}
 #endif
 S390CPU *s390_cpu_addr2state(uint16_t cpu_addr);
 unsigned int s390_cpu_halt(S390CPU *cpu);
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 8c2f228..f65a1d2 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -757,6 +757,18 @@  static void enter_pgmcheck(S390CPU *cpu, uint16_t code)
     kvm_s390_vcpu_interrupt(cpu, &irq);
 }
 
+void kvm_s390_access_exception(S390CPU *cpu, uint16_t code, uint64_t te_code)
+{
+    struct kvm_s390_irq irq = {
+        .type = KVM_S390_PROGRAM_INT,
+        .u.pgm.code = code,
+        .u.pgm.trans_exc_code = te_code,
+        .u.pgm.exc_access_id = te_code & 3,
+    };
+
+    kvm_s390_vcpu_interrupt(cpu, &irq);
+}
+
 static int kvm_sclp_service_call(S390CPU *cpu, struct kvm_run *run,
                                  uint16_t ipbh0)
 {
diff --git a/target-s390x/mmu_helper.c b/target-s390x/mmu_helper.c
index 32a51f3..a1ee992 100644
--- a/target-s390x/mmu_helper.c
+++ b/target-s390x/mmu_helper.c
@@ -46,10 +46,23 @@ 
 #define FS_READ  0x800
 #define FS_WRITE 0x400
 
+static void trigger_access_exception(CPUS390XState *env, uint32_t type,
+                                     uint32_t ilen, uint64_t tec)
+{
+    S390CPU *cpu = s390_env_get_cpu(env);
+
+    if (kvm_enabled()) {
+        kvm_s390_access_exception(cpu, type, tec);
+    } else {
+        CPUState *cs = CPU(cpu);
+        stq_phys(cs->as, env->psa + offsetof(LowCore, trans_exc_code), tec);
+        trigger_pgm_exception(env, type, ilen);
+    }
+}
+
 static void trigger_prot_fault(CPUS390XState *env, target_ulong vaddr,
                                uint64_t asc, int rw, bool exc)
 {
-    CPUState *cs = CPU(s390_env_get_cpu(env));
     uint64_t tec;
 
     tec = vaddr | (rw == 1 ? FS_WRITE : FS_READ) | 4 | asc >> 46;
@@ -60,14 +73,12 @@  static void trigger_prot_fault(CPUS390XState *env, target_ulong vaddr,
         return;
     }
 
-    stq_phys(cs->as, env->psa + offsetof(LowCore, trans_exc_code), tec);
-    trigger_pgm_exception(env, PGM_PROTECTION, ILEN_LATER_INC);
+    trigger_access_exception(env, PGM_PROTECTION, ILEN_LATER_INC, tec);
 }
 
 static void trigger_page_fault(CPUS390XState *env, target_ulong vaddr,
                                uint32_t type, uint64_t asc, int rw, bool exc)
 {
-    CPUState *cs = CPU(s390_env_get_cpu(env));
     int ilen = ILEN_LATER;
     uint64_t tec;
 
@@ -84,8 +95,7 @@  static void trigger_page_fault(CPUS390XState *env, target_ulong vaddr,
         ilen = 2;
     }
 
-    stq_phys(cs->as, env->psa + offsetof(LowCore, trans_exc_code), tec);
-    trigger_pgm_exception(env, type, ilen);
+    trigger_access_exception(env, type, ilen, tec);
 }
 
 /**