Signed-off-by: Emilio G. Cota <c...@braap.org> --- Makefile.target | 1 + aie.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/qemu/aie.h | 49 ++++++++++++++++++++++++++++++++++++++++++++++ translate-all.c | 2 ++ 4 files changed, 109 insertions(+) create mode 100644 aie.c create mode 100644 include/qemu/aie.h
diff --git a/Makefile.target b/Makefile.target index 3e7aafd..840e257 100644 --- a/Makefile.target +++ b/Makefile.target @@ -85,6 +85,7 @@ all: $(PROGS) stap ######################################################### # cpu emulator library obj-y = exec.o translate-all.o cpu-exec.o +obj-y += aie.o obj-y += tcg/tcg.o tcg/tcg-op.o tcg/optimize.o obj-$(CONFIG_TCG_INTERPRETER) += tci.o obj-$(CONFIG_TCG_INTERPRETER) += disas/tci.o diff --git a/aie.c b/aie.c new file mode 100644 index 0000000..588c02b --- /dev/null +++ b/aie.c @@ -0,0 +1,57 @@ +/* + * Atomic instruction emulation (AIE). + * This applies to LL/SC and higher-order atomic instructions. + * More info: + * http://en.wikipedia.org/wiki/Load-link/store-conditional + */ +#include "qemu-common.h" +#include "qemu/radix-tree.h" +#include "qemu/thread.h" +#include "qemu/aie.h" + +#if defined(CONFIG_USER_ONLY) +# define AIE_FULL_ADDR_BITS TARGET_VIRT_ADDR_SPACE_BITS +#else +#if HOST_LONG_BITS < TARGET_PHYS_ADDR_SPACE_BITS +/* in this case QEMU restricts the maximum RAM size to fit in the host */ +# define AIE_FULL_ADDR_BITS HOST_LONG_BITS +#else +# define AIE_FULL_ADDR_BITS TARGET_PHYS_ADDR_SPACE_BITS +#endif +#endif /* CONFIG_USER_ONLY */ + +#define AIE_ADDR_BITS (AIE_FULL_ADDR_BITS - AIE_DISCARD_BITS) +#define AIE_RADIX 8 + +QemuRadixTree aie_rtree; +unsigned long *aie_bm; + +static void *aie_entry_init(unsigned long index) +{ + AIEEntry *entry; + + entry = qemu_memalign(64, sizeof(*entry)); + qemu_spin_init(&entry->lock); + entry->bm_set = false; + return entry; +} + +AIEEntry *aie_entry_get_lock(hwaddr paddr) +{ + aie_addr_t idx = to_aie(paddr); + AIEEntry *e; + + e = qemu_radix_tree_find_alloc(&aie_rtree, idx, aie_entry_init, qemu_vfree); + qemu_spin_lock(&e->lock); + if (!e->bm_set) { + set_bit_atomic(idx & (AIE_BM_NR_ITEMS - 1), aie_bm); + e->bm_set = true; + } + return e; +} + +void aie_init(void) +{ + qemu_radix_tree_init(&aie_rtree, AIE_ADDR_BITS, AIE_RADIX); + aie_bm = bitmap_new(AIE_BM_NR_ITEMS); +} diff --git a/include/qemu/aie.h b/include/qemu/aie.h new file mode 100644 index 0000000..667f36c --- /dev/null +++ b/include/qemu/aie.h @@ -0,0 +1,49 @@ +/* + * Atomic instruction emulation (AIE) + */ +#ifndef AIE_H +#define AIE_H + +#include "qemu/radix-tree.h" +#include "qemu/thread.h" +#include "qemu/bitops.h" + +#include "exec/hwaddr.h" + +typedef hwaddr aie_addr_t; + +typedef struct AIEEntry AIEEntry; + +struct AIEEntry { + union { + struct { + QemuSpin lock; + bool bm_set; + }; + uint8_t pad[64]; + }; +} __attribute((aligned(64))); + +#define AIE_DISCARD_BITS 6 + +#define AIE_BM_BITS 21 +#define AIE_BM_NR_ITEMS BIT(AIE_BM_BITS) + +extern QemuRadixTree aie_rtree; +extern unsigned long *aie_bm; + +static inline aie_addr_t to_aie(hwaddr paddr) +{ + return paddr >> AIE_DISCARD_BITS; +} + +void aie_init(void); + +AIEEntry *aie_entry_get_lock(hwaddr addr); + +static inline bool aie_entry_exists(hwaddr addr) +{ + return test_bit(to_aie(addr) & (AIE_BM_NR_ITEMS - 1), aie_bm); +} + +#endif /* AIE_H */ diff --git a/translate-all.c b/translate-all.c index b873d5c..f07547e 100644 --- a/translate-all.c +++ b/translate-all.c @@ -62,6 +62,7 @@ #include "translate-all.h" #include "qemu/bitmap.h" #include "qemu/timer.h" +#include "qemu/aie.h" //#define DEBUG_TB_INVALIDATE //#define DEBUG_FLUSH @@ -730,6 +731,7 @@ void tcg_exec_init(unsigned long tb_size) tcg_ctx.code_gen_ptr = tcg_ctx.code_gen_buffer; tcg_register_jit(tcg_ctx.code_gen_buffer, tcg_ctx.code_gen_buffer_size); page_init(); + aie_init(); #if !defined(CONFIG_USER_ONLY) || !defined(CONFIG_USE_GUEST_BASE) /* There's no guest base to take into account, so go ahead and initialize the prologue now. */ -- 1.9.1