Skip to content

Commit a36c59d

Browse files
BrunoASMauriciokolerov
authored andcommitted
Helper: Make LF be cleared on usermode interrupt
Fix for issue #48 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]>
1 parent 76e0fa9 commit a36c59d

File tree

1 file changed

+45
-2
lines changed

1 file changed

+45
-2
lines changed

target/arc/op_helper.c

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ static void set_status32(CPUARCState *env, target_ulong value)
7676
#endif
7777
}
7878

79+
static pthread_t last_thread_access;
80+
7981
target_ulong helper_llock(CPUARCState *env, target_ulong addr)
8082
{
8183
assert((addr & 0x3) == 0);
@@ -94,6 +96,11 @@ target_ulong helper_llock(CPUARCState *env, target_ulong addr)
9496
entry->lpa_lf = (haddr & (~LPA_LFS_ALIGNEMENT_MASK));
9597
entry->lpa_lf += 1; /* least significant bit is LF flag */
9698
entry->read_value = ret;
99+
100+
#ifdef CONFIG_USER_ONLY
101+
last_thread_access = pthread_self();
102+
#endif
103+
97104
qemu_mutex_unlock(&entry->mutex);
98105
return ret;
99106
}
@@ -114,6 +121,15 @@ target_ulong helper_scond(CPUARCState *env, target_ulong addr, target_ulong valu
114121
(target_ulong) haddr, (int) LPA_LFS_ENTRY_FOR_PA(haddr));
115122
qemu_mutex_lock(env->arconnect.locked_mutex);
116123
struct lpa_lf_entry *entry = env->arconnect.lpa_lf;
124+
125+
// usermode interrupts don't clear Lock Flag, so we must do so ourselves
126+
#ifdef CONFIG_USER_ONLY
127+
pthread_t current_thread = pthread_self();
128+
if (last_thread_access != current_thread) {
129+
entry->lpa_lf &= -2;
130+
}
131+
#endif
132+
117133
haddr = (haddr & (~LPA_LFS_ALIGNEMENT_MASK));
118134
target_ulong ret = 1;
119135
target_ulong rvalue = cpu_ldl_data_ra(env, addr, GETPC());
@@ -151,6 +167,11 @@ target_ulong helper_llockl(CPUARCState *env, target_ulong addr)
151167
entry->lpa_lf = (haddr & (~LPA_LFS_ALIGNEMENT_MASK));
152168
entry->lpa_lf += 1; /* least significant bit is LF flag */
153169
entry->read_value = ret;
170+
171+
#ifdef CONFIG_USER_ONLY
172+
last_thread_access = pthread_self();
173+
#endif
174+
154175
qemu_mutex_unlock(&entry->mutex);
155176
return ret;
156177
}
@@ -163,8 +184,17 @@ target_ulong helper_scondl(CPUARCState *env, target_ulong addr, target_ulong val
163184
qemu_log_mask(LOG_UNIMP, "0x" TARGET_FMT_lx "SCONDL at addr 0x" TARGET_FMT_lx " at index %d\n",
164185
env->pc,
165186
(target_ulong) haddr, (int) LPA_LFS_ENTRY_FOR_PA(haddr));
166-
struct lpa_lf_entry *entry = env->arconnect.lpa_lf;
167187
qemu_mutex_lock(env->arconnect.locked_mutex);
188+
struct lpa_lf_entry *entry = env->arconnect.lpa_lf;
189+
190+
// usermode interrupts don't clear Lock Flag, so we must do so ourselves
191+
#ifdef CONFIG_USER_ONLY
192+
pthread_t current_thread = pthread_self();
193+
if (last_thread_access != current_thread) {
194+
entry->lpa_lf &= -2;
195+
}
196+
#endif
197+
168198
target_ulong ret = 1;
169199
haddr = (haddr & (~LPA_LFS_ALIGNEMENT_MASK));
170200
target_ulong rvalue = cpu_ldq_data_ra(env, addr, GETPC());
@@ -197,6 +227,10 @@ uint64_t helper_llockd(CPUARCState *env, target_ulong addr)
197227
entry->lpa_lf += 1; /* least significant bit is LF flag */
198228
entry->read_value = ret;
199229

230+
#ifdef CONFIG_USER_ONLY
231+
last_thread_access = pthread_self();
232+
#endif
233+
200234
qemu_mutex_unlock(&entry->mutex);
201235

202236
return ret;
@@ -207,8 +241,17 @@ target_ulong helper_scondd(CPUARCState *env, target_ulong addr, uint64_t value)
207241
hwaddr haddr;
208242
CPUState *cs = env_cpu(env);
209243
arc_get_physical_addr(cs, &haddr, addr, MMU_MEM_WRITE, false, GETPC());
210-
struct lpa_lf_entry *entry = env->arconnect.lpa_lf;
211244
qemu_mutex_lock(env->arconnect.locked_mutex);
245+
struct lpa_lf_entry *entry = env->arconnect.lpa_lf;
246+
247+
// usermode interrupts don't clear Lock Flag, so we must do so ourselves
248+
#ifdef CONFIG_USER_ONLY
249+
pthread_t current_thread = pthread_self();
250+
if (last_thread_access != current_thread) {
251+
entry->lpa_lf &= -2;
252+
}
253+
#endif
254+
212255
target_ulong ret = 1;
213256
addr = (addr & (~LPA_LFS_ALIGNEMENT_MASK));
214257

0 commit comments

Comments
 (0)