addr = env->regs[2];
if (get_user_u64(oldval, env->regs[0])) {
- env->cp15.c6_data = env->regs[0];
+ env->exception.vaddress = env->regs[0];
goto segv;
};
if (get_user_u64(newval, env->regs[1])) {
- env->cp15.c6_data = env->regs[1];
+ env->exception.vaddress = env->regs[1];
goto segv;
};
if (get_user_u64(val, addr)) {
- env->cp15.c6_data = addr;
+ env->exception.vaddress = addr;
goto segv;
}
val = newval;
if (put_user_u64(val, addr)) {
- env->cp15.c6_data = addr;
+ env->exception.vaddress = addr;
goto segv;
};
info.si_errno = 0;
/* XXX: check env->error_code */
info.si_code = TARGET_SEGV_MAPERR;
- info._sifields._sigfault._addr = env->cp15.c6_data;
+ info._sifields._sigfault._addr = env->exception.vaddress;
queue_signal(env, info.si_signo, &info);
end_exclusive();
abort();
}
if (segv) {
- env->cp15.c6_data = addr;
+ env->exception.vaddress = addr;
goto done;
}
if (size == 3) {
uint32_t valhi;
segv = get_user_u32(valhi, addr + 4);
if (segv) {
- env->cp15.c6_data = addr + 4;
+ env->exception.vaddress = addr + 4;
goto done;
}
val = deposit64(val, 32, 32, valhi);
break;
}
if (segv) {
- env->cp15.c6_data = addr;
+ env->exception.vaddress = addr;
goto done;
}
if (size == 3) {
val = env->regs[(env->exclusive_info >> 12) & 0xf];
segv = put_user_u32(val, addr + 4);
if (segv) {
- env->cp15.c6_data = addr + 4;
+ env->exception.vaddress = addr + 4;
goto done;
}
}
case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */
break;
+ case EXCP_STREX:
+ if (!do_strex(env)) {
+ break;
+ }
+ /* fall through for segv */
case EXCP_PREFETCH_ABORT:
- addr = env->cp15.c6_insn;
- goto do_segv;
case EXCP_DATA_ABORT:
- addr = env->cp15.c6_data;
- do_segv:
+ addr = env->exception.vaddress;
{
info.si_signo = SIGSEGV;
info.si_errno = 0;
if (do_kernel_trap(env))
goto error;
break;
- case EXCP_STREX:
- if (do_strex(env)) {
- addr = env->cp15.c6_data;
- goto do_segv;
- }
- break;
default:
error:
fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
abort();
}
if (segv) {
- env->cp15.c6_data = addr;
+ env->exception.vaddress = addr;
goto error;
}
if (val != env->exclusive_val) {
segv = get_user_u64(val, addr + 8);
}
if (segv) {
- env->cp15.c6_data = addr + (size == 2 ? 4 : 8);
+ env->exception.vaddress = addr + (size == 2 ? 4 : 8);
goto error;
}
if (val != env->exclusive_high) {
segv = put_user_u64(val, addr + 8);
}
if (segv) {
- env->cp15.c6_data = addr + (size == 2 ? 4 : 8);
+ env->exception.vaddress = addr + (size == 2 ? 4 : 8);
goto error;
}
}
info._sifields._sigfault._addr = env->pc;
queue_signal(env, info.si_signo, &info);
break;
+ case EXCP_STREX:
+ if (!do_strex_a64(env)) {
+ break;
+ }
+ /* fall through for segv */
case EXCP_PREFETCH_ABORT:
- addr = env->cp15.c6_insn;
- goto do_segv;
case EXCP_DATA_ABORT:
- addr = env->cp15.c6_data;
- do_segv:
+ addr = env->exception.vaddress;
info.si_signo = SIGSEGV;
info.si_errno = 0;
/* XXX: check env->error_code */
queue_signal(env, info.si_signo, &info);
}
break;
- case EXCP_STREX:
- if (do_strex_a64(env)) {
- addr = env->cp15.c6_data;
- goto do_segv;
- }
- break;
default:
fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
trapnr);
ARMCPU *cpu = ARM_CPU(cs);
CPUARMState *env = &cpu->env;
+ env->exception.vaddress = address;
if (rw == 2) {
cs->exception_index = EXCP_PREFETCH_ABORT;
- env->cp15.c6_insn = address;
} else {
cs->exception_index = EXCP_DATA_ABORT;
- env->cp15.c6_data = address;
}
return 1;
}
return;
case EXCP_PREFETCH_ABORT:
case EXCP_DATA_ABORT:
+ /* TODO: if we implemented the MPU registers, this is where we
+ * should set the MMFAR, etc from exception.fsr and exception.vaddress.
+ */
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_MEM);
return;
case EXCP_BKPT:
return;
}
}
- env->cp15.c5_insn = 2;
+ env->exception.fsr = 2;
/* Fall through to prefetch abort. */
case EXCP_PREFETCH_ABORT:
+ env->cp15.c5_insn = env->exception.fsr;
+ env->cp15.c6_insn = env->exception.vaddress;
qemu_log_mask(CPU_LOG_INT, "...with IFSR 0x%x IFAR 0x%x\n",
env->cp15.c5_insn, env->cp15.c6_insn);
new_mode = ARM_CPU_MODE_ABT;
offset = 4;
break;
case EXCP_DATA_ABORT:
+ env->cp15.c5_data = env->exception.fsr;
+ env->cp15.c6_data = env->exception.vaddress;
qemu_log_mask(CPU_LOG_INT, "...with DFSR 0x%x DFAR 0x%x\n",
env->cp15.c5_data, env->cp15.c6_data);
new_mode = ARM_CPU_MODE_ABT;
}
if (access_type == 2) {
- env->cp15.c5_insn = ret;
- env->cp15.c6_insn = address;
cs->exception_index = EXCP_PREFETCH_ABORT;
} else {
- env->cp15.c5_data = ret;
- if (access_type == 1 && arm_feature(env, ARM_FEATURE_V6))
- env->cp15.c5_data |= (1 << 11);
- env->cp15.c6_data = address;
+ if (access_type == 1 && arm_feature(env, ARM_FEATURE_V6)) {
+ ret |= (1 << 11);
+ }
cs->exception_index = EXCP_DATA_ABORT;
}
+ env->exception.vaddress = address;
+ env->exception.fsr = ret;
return 1;
}
VMSTATE_UINT64(env.exclusive_val, ARMCPU),
VMSTATE_UINT64(env.exclusive_high, ARMCPU),
VMSTATE_UINT64(env.features, ARMCPU),
+ VMSTATE_UINT32(env.exception.syndrome, ARMCPU),
+ VMSTATE_UINT32(env.exception.fsr, ARMCPU),
+ VMSTATE_UINT64(env.exception.vaddress, ARMCPU),
VMSTATE_TIMER(gt_timer[GTIMER_PHYS], ARMCPU),
VMSTATE_TIMER(gt_timer[GTIMER_VIRT], ARMCPU),
VMSTATE_END_OF_LIST()