86
86
void s390_cpu_do_interrupt(CPUState *cs)
88
cs->exception_index = -1;
91
int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr address,
88
94
S390CPU *cpu = S390_CPU(cs);
89
CPUS390XState *env = &cpu->env;
91
env->exception_index = -1;
94
int cpu_s390x_handle_mmu_fault(CPUS390XState *env, target_ulong address,
97
env->exception_index = EXCP_PGM;
98
env->int_pgm_code = PGM_ADDRESSING;
96
cs->exception_index = EXCP_PGM;
97
cpu->env.int_pgm_code = PGM_ADDRESSING;
99
98
/* On real machines this value is dropped into LowMem. Since this
100
99
is userland, simply put this someplace that cpu_loop can find it. */
101
env->__excp_addr = address;
100
cpu->env.__excp_addr = address;
108
107
static void trigger_pgm_exception(CPUS390XState *env, uint32_t code,
111
env->exception_index = EXCP_PGM;
110
CPUState *cs = CPU(s390_env_get_cpu(env));
112
cs->exception_index = EXCP_PGM;
112
113
env->int_pgm_code = code;
113
114
env->int_pgm_ilen = ilen;
116
117
static int trans_bits(CPUS390XState *env, uint64_t mode)
119
S390CPU *cpu = s390_env_get_cpu(env);
138
140
static void trigger_prot_fault(CPUS390XState *env, target_ulong vaddr,
143
CPUState *cs = CPU(s390_env_get_cpu(env));
141
144
int ilen = ILEN_LATER_INC;
142
145
int bits = trans_bits(env, mode) | 4;
144
147
DPRINTF("%s: vaddr=%016" PRIx64 " bits=%d\n", __func__, vaddr, bits);
146
stq_phys(env->psa + offsetof(LowCore, trans_exc_code), vaddr | bits);
150
env->psa + offsetof(LowCore, trans_exc_code), vaddr | bits);
147
151
trigger_pgm_exception(env, PGM_PROTECTION, ilen);
150
154
static void trigger_page_fault(CPUS390XState *env, target_ulong vaddr,
151
155
uint32_t type, uint64_t asc, int rw)
157
CPUState *cs = CPU(s390_env_get_cpu(env));
153
158
int ilen = ILEN_LATER;
154
159
int bits = trans_bits(env, asc);
161
166
DPRINTF("%s: vaddr=%016" PRIx64 " bits=%d\n", __func__, vaddr, bits);
163
stq_phys(env->psa + offsetof(LowCore, trans_exc_code), vaddr | bits);
169
env->psa + offsetof(LowCore, trans_exc_code), vaddr | bits);
164
170
trigger_pgm_exception(env, type, ilen);
218
225
/* XXX region protection flags */
219
226
/* *flags &= ~PAGE_WRITE */
221
new_asce = ldq_phys(origin + offs);
228
new_asce = ldq_phys(cs->as, origin + offs);
222
229
PTE_DPRINTF("%s: 0x%" PRIx64 " + 0x%" PRIx64 " => 0x%016" PRIx64 "\n",
223
230
__func__, origin, offs, new_asce);
377
int cpu_s390x_handle_mmu_fault(CPUS390XState *env, target_ulong orig_vaddr,
384
int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr orig_vaddr,
387
S390CPU *cpu = S390_CPU(cs);
388
CPUS390XState *env = &cpu->env;
380
389
uint64_t asc = env->psw.mask & PSW_MASK_ASC;
381
390
target_ulong vaddr, raddr;
384
DPRINTF("%s: address 0x%" PRIx64 " rw %d mmu_idx %d\n",
393
DPRINTF("%s: address 0x%" VADDR_PRIx " rw %d mmu_idx %d\n",
385
394
__func__, orig_vaddr, rw, mmu_idx);
387
396
orig_vaddr &= TARGET_PAGE_MASK;
408
417
DPRINTF("%s: set tlb %" PRIx64 " -> %" PRIx64 " (%x)\n", __func__,
409
418
(uint64_t)vaddr, (uint64_t)raddr, prot);
411
tlb_set_page(env, orig_vaddr, raddr, prot,
420
tlb_set_page(cs, orig_vaddr, raddr, prot,
412
421
mmu_idx, TARGET_PAGE_SIZE);
472
481
static LowCore *cpu_map_lowcore(CPUS390XState *env)
483
S390CPU *cpu = s390_env_get_cpu(env);
474
484
LowCore *lowcore;
475
485
hwaddr len = sizeof(LowCore);
477
487
lowcore = cpu_physical_memory_map(env->psa, &len, 1);
479
489
if (len < sizeof(LowCore)) {
480
cpu_abort(env, "Could not map lowcore\n");
490
cpu_abort(CPU(cpu), "Could not map lowcore\n");
576
586
static void do_ext_interrupt(CPUS390XState *env)
588
S390CPU *cpu = s390_env_get_cpu(env);
578
589
uint64_t mask, addr;
579
590
LowCore *lowcore;
582
593
if (!(env->psw.mask & PSW_MASK_EXT)) {
583
cpu_abort(env, "Ext int w/o ext mask\n");
594
cpu_abort(CPU(cpu), "Ext int w/o ext mask\n");
586
597
if (env->ext_index < 0 || env->ext_index > MAX_EXT_QUEUE) {
587
cpu_abort(env, "Ext queue overrun: %d\n", env->ext_index);
598
cpu_abort(CPU(cpu), "Ext queue overrun: %d\n", env->ext_index);
590
601
q = &env->ext_queue[env->ext_index];
633
645
if (env->io_index[isc] > MAX_IO_QUEUE) {
634
cpu_abort(env, "I/O queue overrun for isc %d: %d\n",
646
cpu_abort(CPU(cpu), "I/O queue overrun for isc %d: %d\n",
635
647
isc, env->io_index[isc]);
679
691
static void do_mchk_interrupt(CPUS390XState *env)
693
S390CPU *cpu = s390_env_get_cpu(env);
681
694
uint64_t mask, addr;
682
695
LowCore *lowcore;
686
699
if (!(env->psw.mask & PSW_MASK_MCHECK)) {
687
cpu_abort(env, "Machine check w/o mchk mask\n");
700
cpu_abort(CPU(cpu), "Machine check w/o mchk mask\n");
690
703
if (env->mchk_index < 0 || env->mchk_index > MAX_MCHK_QUEUE) {
691
cpu_abort(env, "Mchk queue overrun: %d\n", env->mchk_index);
704
cpu_abort(CPU(cpu), "Mchk queue overrun: %d\n", env->mchk_index);
694
707
q = &env->mchk_queue[env->mchk_index];
696
709
if (q->type != 1) {
697
710
/* Don't know how to handle this... */
698
cpu_abort(env, "Unknown machine check type %d\n", q->type);
711
cpu_abort(CPU(cpu), "Unknown machine check type %d\n", q->type);
700
713
if (!(env->cregs[14] & (1 << 28))) {
701
714
/* CRW machine checks disabled */
744
757
CPUS390XState *env = &cpu->env;
746
759
qemu_log_mask(CPU_LOG_INT, "%s: %d at pc=%" PRIx64 "\n",
747
__func__, env->exception_index, env->psw.addr);
760
__func__, cs->exception_index, env->psw.addr);
749
762
s390_add_running_cpu(cpu);
750
763
/* handle machine checks */
751
764
if ((env->psw.mask & PSW_MASK_MCHECK) &&
752
(env->exception_index == -1)) {
765
(cs->exception_index == -1)) {
753
766
if (env->pending_int & INTERRUPT_MCHK) {
754
env->exception_index = EXCP_MCHK;
767
cs->exception_index = EXCP_MCHK;
757
770
/* handle external interrupts */
758
771
if ((env->psw.mask & PSW_MASK_EXT) &&
759
env->exception_index == -1) {
772
cs->exception_index == -1) {
760
773
if (env->pending_int & INTERRUPT_EXT) {
761
774
/* code is already in env */
762
env->exception_index = EXCP_EXT;
775
cs->exception_index = EXCP_EXT;
763
776
} else if (env->pending_int & INTERRUPT_TOD) {
764
777
cpu_inject_ext(cpu, 0x1004, 0, 0);
765
env->exception_index = EXCP_EXT;
778
cs->exception_index = EXCP_EXT;
766
779
env->pending_int &= ~INTERRUPT_EXT;
767
780
env->pending_int &= ~INTERRUPT_TOD;
768
781
} else if (env->pending_int & INTERRUPT_CPUTIMER) {
769
782
cpu_inject_ext(cpu, 0x1005, 0, 0);
770
env->exception_index = EXCP_EXT;
783
cs->exception_index = EXCP_EXT;
771
784
env->pending_int &= ~INTERRUPT_EXT;
772
785
env->pending_int &= ~INTERRUPT_TOD;
775
788
/* handle I/O interrupts */
776
789
if ((env->psw.mask & PSW_MASK_IO) &&
777
(env->exception_index == -1)) {
790
(cs->exception_index == -1)) {
778
791
if (env->pending_int & INTERRUPT_IO) {
779
env->exception_index = EXCP_IO;
792
cs->exception_index = EXCP_IO;
783
switch (env->exception_index) {
796
switch (cs->exception_index) {
785
798
do_program_interrupt(env);