[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [RFC 6/8] aie: add target helpers
From: |
Emilio G. Cota |
Subject: |
[Qemu-devel] [RFC 6/8] aie: add target helpers |
Date: |
Fri, 8 May 2015 17:02:12 -0400 |
Signed-off-by: Emilio G. Cota <address@hidden>
---
aie-helper.c | 179 ++++++++++++++++++++++++++++++++++++++++++++++
include/exec/cpu-defs.h | 5 ++
include/qemu/aie-helper.h | 21 ++++++
3 files changed, 205 insertions(+)
create mode 100644 aie-helper.c
create mode 100644 include/qemu/aie-helper.h
diff --git a/aie-helper.c b/aie-helper.c
new file mode 100644
index 0000000..8bc8955
--- /dev/null
+++ b/aie-helper.c
@@ -0,0 +1,179 @@
+/*
+ * To be included directly from the target's helper.c
+ */
+#include "qemu/aie.h"
+
+#ifdef CONFIG_USER_ONLY
+static inline hwaddr h_get_ld_phys(CPUArchState *env, target_ulong vaddr)
+{
+ return vaddr;
+}
+
+static inline hwaddr h_get_st_phys(CPUArchState *env, target_ulong vaddr)
+{
+ return vaddr;
+}
+#else
+/* these need to be macros due to GETRA() */
+#define h_get_ld_phys(env, vaddr) \
+ helper_ret_get_ld_phys(env, vaddr, cpu_mmu_index(env), GETRA())
+#define h_get_st_phys(env, vaddr) \
+ helper_ret_get_st_phys(env, vaddr, cpu_mmu_index(env), GETRA())
+#endif /* CONFIG_USER_ONLY */
+
+static inline void h_aie_lock(CPUArchState *env, hwaddr paddr)
+{
+ AIEEntry *entry = aie_entry_get_lock(paddr);
+
+ env->aie_entry = entry;
+ env->aie_locked = true;
+}
+
+static inline void h_aie_unlock(CPUArchState *env)
+{
+ assert(env->aie_entry && env->aie_locked);
+ qemu_mutex_unlock(&env->aie_entry->lock);
+ env->aie_locked = false;
+}
+
+static inline void h_aie_unlock__done(CPUArchState *env)
+{
+ h_aie_unlock(env);
+ env->aie_entry = NULL;
+}
+
+void HELPER(aie_llsc_st_tracking_enable)(CPUArchState *env)
+{
+ CPUState *other_cs;
+
+ if (likely(atomic_read(&env->aie_llsc_st_tracking))) {
+ return;
+ }
+ CPU_FOREACH(other_cs) {
+ CPUArchState *other_env = other_cs->env_ptr;
+
+ atomic_set(&other_env->aie_llsc_st_tracking, true);
+ }
+}
+
+void HELPER(aie_ld_lock)(CPUArchState *env, target_ulong vaddr)
+{
+ hwaddr paddr;
+
+ assert(!env->aie_locked);
+ paddr = h_get_ld_phys(env, vaddr);
+ h_aie_lock(env, paddr);
+}
+
+void HELPER(aie_st_lock)(CPUArchState *env, target_ulong vaddr)
+{
+ hwaddr paddr;
+
+ assert(!env->aie_locked);
+ paddr = h_get_st_phys(env, vaddr);
+ h_aie_lock(env, paddr);
+}
+
+void HELPER(aie_insert_lock)(CPUArchState *env, target_ulong vaddr)
+{
+ AIEEntry *entry;
+ hwaddr paddr;
+
+ assert(!env->aie_locked);
+ paddr = h_get_ld_phys(env, vaddr);
+ entry = aie_entry_get_lock(paddr);
+
+ tiny_set_insert(&entry->ts, current_cpu);
+ env->aie_entry = entry;
+ env->aie_locked = true;
+}
+
+uint32_t HELPER(aie_contains_lock)(CPUArchState *env)
+{
+ AIEEntry *entry = env->aie_entry;
+
+ /* clrex could arrive between ldrex and strex due to preemption */
+ if (unlikely(entry == NULL)) {
+ return -1;
+ }
+ qemu_mutex_lock(&entry->lock);
+ env->aie_locked = true;
+ if (tiny_set_contains(&entry->ts, current_cpu)) {
+ tiny_set_remove_all(&entry->ts);
+ return 0;
+ }
+ qemu_mutex_unlock(&entry->lock);
+ env->aie_locked = false;
+ env->aie_entry = NULL;
+ return -1;
+}
+
+void HELPER(aie_unlock)(CPUArchState *env)
+{
+ h_aie_unlock(env);
+}
+
+void HELPER(aie_unlock__done)(CPUArchState *env)
+{
+ h_aie_unlock__done(env);
+}
+
+void HELPER(aie_clear)(CPUArchState *env)
+{
+ AIEEntry *entry = env->aie_entry;
+
+ assert(!env->aie_locked);
+ if (!entry) {
+ return;
+ }
+
+ qemu_mutex_lock(&env->aie_entry->lock);
+ tiny_set_remove(&entry->ts, current_cpu);
+ qemu_mutex_unlock(&env->aie_entry->lock);
+ env->aie_entry = NULL;
+}
+
+void HELPER(aie_ld_pre)(CPUArchState *env, target_ulong vaddr)
+{
+ if (likely(!env->aie_lock_enabled) || env->aie_locked) {
+ return;
+ }
+ helper_aie_ld_lock(env, vaddr);
+}
+
+void HELPER(aie_st_pre)(CPUArchState *env, target_ulong vaddr)
+{
+ if (unlikely(env->aie_lock_enabled)) {
+ if (env->aie_locked) {
+ return;
+ }
+ helper_aie_st_lock(env, vaddr);
+ } else {
+ hwaddr paddr = h_get_st_phys(env, vaddr);
+
+ if (unlikely(aie_entry_exists(paddr))) {
+ h_aie_lock(env, paddr);
+ }
+ }
+}
+
+void HELPER(aie_llsc_st_pre)(CPUArchState *env, target_ulong vaddr)
+{
+ hwaddr paddr;
+
+ assert(!env->aie_locked);
+ if (!env->aie_llsc_st_tracking) {
+ return;
+ }
+ paddr = h_get_st_phys(env, vaddr);
+ if (unlikely(aie_entry_exists(paddr))) {
+ h_aie_lock(env, paddr);
+ }
+}
+
+void HELPER(aie_llsc_st_post)(CPUArchState *env)
+{
+ if (unlikely(env->aie_locked)) {
+ h_aie_unlock__done(env);
+ }
+}
diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
index 67aa0a0..8891f16 100644
--- a/include/exec/cpu-defs.h
+++ b/include/exec/cpu-defs.h
@@ -27,6 +27,7 @@
#include <inttypes.h>
#include "qemu/osdep.h"
#include "qemu/queue.h"
+#include "qemu/aie.h"
#ifndef CONFIG_USER_ONLY
#include "exec/hwaddr.h"
#endif
@@ -135,5 +136,9 @@ typedef struct CPUIOTLBEntry {
#define CPU_COMMON \
/* soft mmu support */ \
CPU_COMMON_TLB \
+ AIEEntry *aie_entry; \
+ bool aie_locked; \
+ bool aie_lock_enabled; \
+ bool aie_llsc_st_tracking; \
#endif
diff --git a/include/qemu/aie-helper.h b/include/qemu/aie-helper.h
new file mode 100644
index 0000000..7605e07
--- /dev/null
+++ b/include/qemu/aie-helper.h
@@ -0,0 +1,21 @@
+#ifdef TARGET_ARM
+#define AIE_VADDR_TCG_TYPE glue(i, TARGET_VIRT_ADDR_SPACE_BITS)
+#else
+#define AIE_VADDR_TCG_TYPE tl
+#endif /* TARGET_ARM */
+
+DEF_HELPER_2(aie_ld_pre, void, env, AIE_VADDR_TCG_TYPE)
+DEF_HELPER_2(aie_st_pre, void, env, AIE_VADDR_TCG_TYPE)
+DEF_HELPER_2(aie_llsc_st_pre, void, env, AIE_VADDR_TCG_TYPE)
+DEF_HELPER_1(aie_llsc_st_post, void, env)
+DEF_HELPER_1(aie_llsc_st_tracking_enable, void, env)
+
+DEF_HELPER_2(aie_ld_lock, void, env, AIE_VADDR_TCG_TYPE)
+DEF_HELPER_2(aie_st_lock, void, env, AIE_VADDR_TCG_TYPE)
+DEF_HELPER_2(aie_insert_lock, void, env, AIE_VADDR_TCG_TYPE)
+DEF_HELPER_1(aie_contains_lock, i32, env)
+DEF_HELPER_1(aie_unlock, void, env)
+DEF_HELPER_1(aie_unlock__done, void, env)
+DEF_HELPER_1(aie_clear, void, env)
+
+#undef AIE_VADDR_TCG_TYPE
--
1.8.3
- [Qemu-devel] [RFC 0/8] Helper-based Atomic Instruction Emulation (AIE), Emilio G. Cota, 2015/05/08
- [Qemu-devel] [RFC 1/8] cputlb: add physical address to CPUTLBEntry, Emilio G. Cota, 2015/05/08
- [Qemu-devel] [RFC 3/8] tiny_set: add module to test for membership in a tiny set of pointers, Emilio G. Cota, 2015/05/08
- [Qemu-devel] [RFC 2/8] softmmu: add helpers to get ld/st physical addresses, Emilio G. Cota, 2015/05/08
- [Qemu-devel] [RFC 4/8] radix-tree: add generic lockless radix tree module, Emilio G. Cota, 2015/05/08
- [Qemu-devel] [RFC 5/8] aie: add module for Atomic Instruction Emulation, Emilio G. Cota, 2015/05/08
- [Qemu-devel] [RFC 6/8] aie: add target helpers,
Emilio G. Cota <=
- [Qemu-devel] [RFC 7/8] target-arm: emulate atomic instructions using AIE, Emilio G. Cota, 2015/05/08
- [Qemu-devel] [RFC 8/8] target-i386: emulate atomic instructions using AIE, Emilio G. Cota, 2015/05/08
- Re: [Qemu-devel] [RFC 0/8] Helper-based Atomic Instruction Emulation (AIE), Frederic Konrad, 2015/05/11