Skip to content

Commit

Permalink
target/arc: Make LF be cleared on usermode interrupt #48
Browse files Browse the repository at this point in the history
Since an interrupt requires LF to be cleared and there is no hook for
usermode interrupts, we save/validate current thread id to detect
preemption and clear LF. This only needs to be done where it is
relevant for LF (llock/scond variant helpers).

Signed-off-by: BrunoASMauricio <[email protected]>
  • Loading branch information
BrunoASMauricio authored and kolerov committed Jul 9, 2024
1 parent 6492f39 commit 5f1aa65
Showing 1 changed file with 45 additions and 2 deletions.
47 changes: 45 additions & 2 deletions target/arc/op_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ static void set_status32(CPUARCState *env, target_ulong value)
#endif
}

static pthread_t last_thread_access;

target_ulong helper_llock(CPUARCState *env, target_ulong addr)
{
assert((addr & 0x3) == 0);
Expand All @@ -94,6 +96,11 @@ target_ulong helper_llock(CPUARCState *env, target_ulong addr)
entry->lpa_lf = (haddr & (~LPA_LFS_ALIGNEMENT_MASK));
entry->lpa_lf |= 1; /* least significant bit is LF flag */
entry->read_value = ret;

#ifdef CONFIG_USER_ONLY
last_thread_access = pthread_self();
#endif

qemu_mutex_unlock(&entry->mutex);
return ret;
}
Expand All @@ -114,6 +121,15 @@ target_ulong helper_scond(CPUARCState *env, target_ulong addr, target_ulong valu
(target_ulong) haddr, (int) LPA_LFS_ENTRY_FOR_PA(haddr));
qemu_mutex_lock(env->arconnect.locked_mutex);
struct lpa_lf_entry *entry = env->arconnect.lpa_lf;

// usermode interrupts don't clear Lock Flag, so we must do so ourselves
#ifdef CONFIG_USER_ONLY
pthread_t current_thread = pthread_self();
if (last_thread_access != current_thread) {
entry->lpa_lf &= -2;
}
#endif

haddr = (haddr & (~LPA_LFS_ALIGNEMENT_MASK));
target_ulong ret = 1;
target_ulong rvalue = cpu_ldl_data_ra(env, addr, GETPC());
Expand Down Expand Up @@ -151,6 +167,11 @@ target_ulong helper_llockl(CPUARCState *env, target_ulong addr)
entry->lpa_lf = (haddr & (~LPA_LFS_ALIGNEMENT_MASK));
entry->lpa_lf |= 1; /* least significant bit is LF flag */
entry->read_value = ret;

#ifdef CONFIG_USER_ONLY
last_thread_access = pthread_self();
#endif

qemu_mutex_unlock(&entry->mutex);
return ret;
}
Expand All @@ -163,8 +184,17 @@ target_ulong helper_scondl(CPUARCState *env, target_ulong addr, target_ulong val
qemu_log_mask(LOG_UNIMP, "0x" TARGET_FMT_lx "SCONDL at addr 0x" TARGET_FMT_lx " at index %d\n",
env->pc,
(target_ulong) haddr, (int) LPA_LFS_ENTRY_FOR_PA(haddr));
struct lpa_lf_entry *entry = env->arconnect.lpa_lf;
qemu_mutex_lock(env->arconnect.locked_mutex);
struct lpa_lf_entry *entry = env->arconnect.lpa_lf;

// usermode interrupts don't clear Lock Flag, so we must do so ourselves
#ifdef CONFIG_USER_ONLY
pthread_t current_thread = pthread_self();
if (last_thread_access != current_thread) {
entry->lpa_lf &= -2;
}
#endif

target_ulong ret = 1;
haddr = (haddr & (~LPA_LFS_ALIGNEMENT_MASK));
target_ulong rvalue = cpu_ldq_data_ra(env, addr, GETPC());
Expand Down Expand Up @@ -197,6 +227,10 @@ uint64_t helper_llockd(CPUARCState *env, target_ulong addr)
entry->lpa_lf |= 1; /* least significant bit is LF flag */
entry->read_value = ret;

#ifdef CONFIG_USER_ONLY
last_thread_access = pthread_self();
#endif

qemu_mutex_unlock(&entry->mutex);

return ret;
Expand All @@ -207,8 +241,17 @@ target_ulong helper_scondd(CPUARCState *env, target_ulong addr, uint64_t value)
hwaddr haddr;
CPUState *cs = env_cpu(env);
arc_get_physical_addr(cs, &haddr, addr, MMU_MEM_WRITE, false, GETPC());
struct lpa_lf_entry *entry = env->arconnect.lpa_lf;
qemu_mutex_lock(env->arconnect.locked_mutex);
struct lpa_lf_entry *entry = env->arconnect.lpa_lf;

// usermode interrupts don't clear Lock Flag, so we must do so ourselves
#ifdef CONFIG_USER_ONLY
pthread_t current_thread = pthread_self();
if (last_thread_access != current_thread) {
entry->lpa_lf &= -2;
}
#endif

target_ulong ret = 1;
addr = (addr & (~LPA_LFS_ALIGNEMENT_MASK));

Expand Down

0 comments on commit 5f1aa65

Please sign in to comment.