mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-02 07:13:54 -06:00
ARM atomic ops rewrite
Implement ARMv6 atomic ops (ldrex/strex) using the same trick as PPC. Signed-off-by: Paul Brook <paul@codesourcery.com>
This commit is contained in:
parent
eee4850422
commit
426f5abcaa
5 changed files with 251 additions and 176 deletions
|
@ -524,6 +524,81 @@ do_kernel_trap(CPUARMState *env)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int do_strex(CPUARMState *env)
|
||||
{
|
||||
uint32_t val;
|
||||
int size;
|
||||
int rc = 1;
|
||||
int segv = 0;
|
||||
uint32_t addr;
|
||||
start_exclusive();
|
||||
addr = env->exclusive_addr;
|
||||
if (addr != env->exclusive_test) {
|
||||
goto fail;
|
||||
}
|
||||
size = env->exclusive_info & 0xf;
|
||||
switch (size) {
|
||||
case 0:
|
||||
segv = get_user_u8(val, addr);
|
||||
break;
|
||||
case 1:
|
||||
segv = get_user_u16(val, addr);
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
segv = get_user_u32(val, addr);
|
||||
break;
|
||||
}
|
||||
if (segv) {
|
||||
env->cp15.c6_data = addr;
|
||||
goto done;
|
||||
}
|
||||
if (val != env->exclusive_val) {
|
||||
goto fail;
|
||||
}
|
||||
if (size == 3) {
|
||||
segv = get_user_u32(val, addr + 4);
|
||||
if (segv) {
|
||||
env->cp15.c6_data = addr + 4;
|
||||
goto done;
|
||||
}
|
||||
if (val != env->exclusive_high) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
val = env->regs[(env->exclusive_info >> 8) & 0xf];
|
||||
switch (size) {
|
||||
case 0:
|
||||
segv = put_user_u8(val, addr);
|
||||
break;
|
||||
case 1:
|
||||
segv = put_user_u16(val, addr);
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
segv = put_user_u32(val, addr);
|
||||
break;
|
||||
}
|
||||
if (segv) {
|
||||
env->cp15.c6_data = addr;
|
||||
goto done;
|
||||
}
|
||||
if (size == 3) {
|
||||
val = env->regs[(env->exclusive_info >> 12) & 0xf];
|
||||
segv = put_user_u32(val, addr);
|
||||
if (segv) {
|
||||
env->cp15.c6_data = addr + 4;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
rc = 0;
|
||||
fail:
|
||||
env->regs[(env->exclusive_info >> 4) & 0xf] = rc;
|
||||
done:
|
||||
end_exclusive();
|
||||
return segv;
|
||||
}
|
||||
|
||||
void cpu_loop(CPUARMState *env)
|
||||
{
|
||||
int trapnr;
|
||||
|
@ -717,6 +792,11 @@ void cpu_loop(CPUARMState *env)
|
|||
if (do_kernel_trap(env))
|
||||
goto error;
|
||||
break;
|
||||
case EXCP_STREX:
|
||||
if (do_strex(env)) {
|
||||
addr = env->cp15.c6_data;
|
||||
goto do_segv;
|
||||
}
|
||||
default:
|
||||
error:
|
||||
fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue