summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--target-s390x/cpu.h5
-rw-r--r--target-s390x/kvm.c12
-rw-r--r--target-s390x/mmu_helper.c22
3 files changed, 33 insertions, 6 deletions
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index c24ca5f7fc..f8cea308b6 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 8c2f228fa6..f65a1d26a5 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 32a51f32fb..a1ee992f75 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);
 }
 
 /**