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); } /**