From: Frederic Konrad <fred.konrad@greensocs.com>
To: "Alex Bennée" <alex.bennee@linaro.org>
Cc: mttcg@listserver.greensocs.com, peter.maydell@linaro.org,
a.spyridakis@virtualopensystems.com, mark.burton@greensocs.com,
agraf@suse.de, qemu-devel@nongnu.org,
guillaume.delbergue@greensocs.com, pbonzini@redhat.com,
alistair.francis@xilinx.com
Subject: Re: [Qemu-devel] [RFC PATCH V6 05/18] protect TBContext with tb_lock.
Date: Tue, 07 Jul 2015 15:16:43 +0200 [thread overview]
Message-ID: <559BD13B.4080804@greensocs.com> (raw)
In-Reply-To: <87pp449my7.fsf@linaro.org>
On 07/07/2015 14:22, Alex Bennée wrote:
> fred.konrad@greensocs.com writes:
>
>> From: KONRAD Frederic <fred.konrad@greensocs.com>
>>
>> This protects TBContext with tb_lock to make tb_* thread safe.
>>
>> We can still have issue with tb_flush in case of multithread TCG:
>> An other CPU can be executing code during a flush.
>>
>> This can be fixed later by making all other TCG thread exiting before calling
>> tb_flush().
>>
>> tb_find_slow is separated into tb_find_slow and tb_find_physical as the whole
>> tb_find_slow doesn't require to lock the tb.
>>
>> Signed-off-by: KONRAD Frederic <fred.konrad@greensocs.com>
> So my comments from earlier about the different locking between
> CONFIG_USER and system emulation still stand. Ultimately we need a good
> reason (or an abstraction) before sprinkling #ifdefs in the code if only
> for ease of reading.
True.
>> Changes:
>> V1 -> V2:
>> * Drop a tb_lock arround tb_find_fast in cpu-exec.c.
>> ---
>> cpu-exec.c | 60 ++++++++++++++--------
>> target-arm/translate.c | 5 ++
>> tcg/tcg.h | 7 +++
>> translate-all.c | 137 ++++++++++++++++++++++++++++++++++++++-----------
>> 4 files changed, 158 insertions(+), 51 deletions(-)
>>
>> diff --git a/cpu-exec.c b/cpu-exec.c
>> index d6336d9..5d9b518 100644
>> --- a/cpu-exec.c
>> +++ b/cpu-exec.c
>> @@ -130,6 +130,8 @@ static void init_delay_params(SyncClocks *sc, const CPUState *cpu)
>> void cpu_loop_exit(CPUState *cpu)
>> {
>> cpu->current_tb = NULL;
>> + /* Release those mutex before long jump so other thread can work. */
>> + tb_lock_reset();
>> siglongjmp(cpu->jmp_env, 1);
>> }
>>
>> @@ -142,6 +144,8 @@ void cpu_resume_from_signal(CPUState *cpu, void *puc)
>> /* XXX: restore cpu registers saved in host registers */
>>
>> cpu->exception_index = -1;
>> + /* Release those mutex before long jump so other thread can work. */
>> + tb_lock_reset();
>> siglongjmp(cpu->jmp_env, 1);
>> }
>>
>> @@ -253,12 +257,9 @@ static void cpu_exec_nocache(CPUArchState *env, int max_cycles,
>> tb_free(tb);
>> }
>>
>> -static TranslationBlock *tb_find_slow(CPUArchState *env,
>> - target_ulong pc,
>> - target_ulong cs_base,
>> - uint64_t flags)
>> +static TranslationBlock *tb_find_physical(CPUArchState *env, target_ulong pc,
>> + target_ulong cs_base, uint64_t flags)
>> {
> As Paolo has already mentioned comments on functions expecting to have
> locks held when called.
Ok, will do that.
>> - CPUState *cpu = ENV_GET_CPU(env);
>> TranslationBlock *tb, **ptb1;
>> unsigned int h;
>> tb_page_addr_t phys_pc, phys_page1;
>> @@ -273,8 +274,9 @@ static TranslationBlock *tb_find_slow(CPUArchState *env,
>> ptb1 = &tcg_ctx.tb_ctx.tb_phys_hash[h];
>> for(;;) {
>> tb = *ptb1;
>> - if (!tb)
>> - goto not_found;
>> + if (!tb) {
>> + return tb;
>> + }
>> if (tb->pc == pc &&
>> tb->page_addr[0] == phys_page1 &&
>> tb->cs_base == cs_base &&
>> @@ -282,28 +284,43 @@ static TranslationBlock *tb_find_slow(CPUArchState *env,
>> /* check next page if needed */
>> if (tb->page_addr[1] != -1) {
>> tb_page_addr_t phys_page2;
>> -
>> virt_page2 = (pc & TARGET_PAGE_MASK) +
>> TARGET_PAGE_SIZE;
>> phys_page2 = get_page_addr_code(env, virt_page2);
>> - if (tb->page_addr[1] == phys_page2)
>> - goto found;
>> + if (tb->page_addr[1] == phys_page2) {
>> + return tb;
>> + }
>> } else {
>> - goto found;
>> + return tb;
>> }
>> }
>> ptb1 = &tb->phys_hash_next;
>> }
>> - not_found:
>> - /* if no translated code available, then translate it now */
>> - tb = tb_gen_code(cpu, pc, cs_base, flags, 0);
>> -
>> - found:
>> - /* Move the last found TB to the head of the list */
>> - if (likely(*ptb1)) {
>> - *ptb1 = tb->phys_hash_next;
>> - tb->phys_hash_next = tcg_ctx.tb_ctx.tb_phys_hash[h];
>> - tcg_ctx.tb_ctx.tb_phys_hash[h] = tb;
>> + return tb;
>> +}
>> +
>> +static TranslationBlock *tb_find_slow(CPUArchState *env, target_ulong pc,
>> + target_ulong cs_base, uint64_t flags)
>> +{
>> + /*
>> + * First try to get the tb if we don't find it we need to lock and compile
>> + * it.
>> + */
>> + CPUState *cpu = ENV_GET_CPU(env);
>> + TranslationBlock *tb;
>> +
>> + tb = tb_find_physical(env, pc, cs_base, flags);
>> + if (!tb) {
>> + tb_lock();
>> + /*
>> + * Retry to get the TB in case a CPU just translate it to avoid having
>> + * duplicated TB in the pool.
>> + */
>> + tb = tb_find_physical(env, pc, cs_base, flags);
>> + if (!tb) {
>> + tb = tb_gen_code(cpu, pc, cs_base, flags, 0);
>> + }
>> + tb_unlock();
>> }
>> /* we add the TB in the virtual pc hash table */
>> cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
>> @@ -326,6 +343,7 @@ static inline TranslationBlock *tb_find_fast(CPUArchState *env)
>> tb->flags != flags)) {
>> tb = tb_find_slow(env, pc, cs_base, flags);
>> }
>> +
>> return tb;
>> }
>>
>> diff --git a/target-arm/translate.c b/target-arm/translate.c
>> index 971b6db..47345aa 100644
>> --- a/target-arm/translate.c
>> +++ b/target-arm/translate.c
>> @@ -11162,6 +11162,8 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
>>
>> dc->tb = tb;
>>
>> + tb_lock();
>> +
>> dc->is_jmp = DISAS_NEXT;
>> dc->pc = pc_start;
>> dc->singlestep_enabled = cs->singlestep_enabled;
>> @@ -11499,6 +11501,7 @@ done_generating:
>> tb->size = dc->pc - pc_start;
>> tb->icount = num_insns;
>> }
>> + tb_unlock();
>> }
>>
>> void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
>> @@ -11567,6 +11570,7 @@ void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
>>
>> void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb, int pc_pos)
>> {
>> + tb_lock();
>> if (is_a64(env)) {
>> env->pc = tcg_ctx.gen_opc_pc[pc_pos];
>> env->condexec_bits = 0;
>> @@ -11574,4 +11578,5 @@ void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb, int pc_pos)
>> env->regs[15] = tcg_ctx.gen_opc_pc[pc_pos];
>> env->condexec_bits = gen_opc_condexec_bits[pc_pos];
>> }
>> + tb_unlock();
>> }
>> diff --git a/tcg/tcg.h b/tcg/tcg.h
>> index 41e4869..032fe10 100644
>> --- a/tcg/tcg.h
>> +++ b/tcg/tcg.h
>> @@ -592,17 +592,24 @@ void *tcg_malloc_internal(TCGContext *s, int size);
>> void tcg_pool_reset(TCGContext *s);
>> void tcg_pool_delete(TCGContext *s);
>>
>> +void tb_lock(void);
>> +void tb_unlock(void);
>> +void tb_lock_reset(void);
>> +
>> static inline void *tcg_malloc(int size)
>> {
>> TCGContext *s = &tcg_ctx;
>> uint8_t *ptr, *ptr_end;
>> + tb_lock();
>> size = (size + sizeof(long) - 1) & ~(sizeof(long) - 1);
>> ptr = s->pool_cur;
>> ptr_end = ptr + size;
>> if (unlikely(ptr_end > s->pool_end)) {
>> + tb_unlock();
>> return tcg_malloc_internal(&tcg_ctx, size);
> If the purpose of the lock is to protect the global tcg_ctx then we
> shouldn't be unlocking before calling the _internal function which also
> messes with the context.
>
Good point! I missed that.
>> } else {
>> s->pool_cur = ptr_end;
>> + tb_unlock();
>> return ptr;
>> }
>> }
>> diff --git a/translate-all.c b/translate-all.c
>> index b6b0e1c..c25b79b 100644
>> --- a/translate-all.c
>> +++ b/translate-all.c
>> @@ -127,6 +127,34 @@ static void *l1_map[V_L1_SIZE];
>> /* code generation context */
>> TCGContext tcg_ctx;
>>
>> +/* translation block context */
>> +__thread volatile int have_tb_lock;
>> +
>> +void tb_lock(void)
>> +{
>> + if (!have_tb_lock) {
>> + qemu_mutex_lock(&tcg_ctx.tb_ctx.tb_lock);
>> + }
>> + have_tb_lock++;
>> +}
>> +
>> +void tb_unlock(void)
>> +{
>> + assert(have_tb_lock > 0);
>> + have_tb_lock--;
>> + if (!have_tb_lock) {
>> + qemu_mutex_unlock(&tcg_ctx.tb_ctx.tb_lock);
>> + }
>> +}
>> +
>> +void tb_lock_reset(void)
>> +{
>> + if (have_tb_lock) {
>> + qemu_mutex_unlock(&tcg_ctx.tb_ctx.tb_lock);
>> + }
>> + have_tb_lock = 0;
>> +}
>> +
>> static void tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
>> tb_page_addr_t phys_page2);
>> static TranslationBlock *tb_find_pc(uintptr_t tc_ptr);
>> @@ -215,6 +243,7 @@ static int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
>> #ifdef CONFIG_PROFILER
>> ti = profile_getclock();
>> #endif
>> + tb_lock();
>> tcg_func_start(s);
>>
>> gen_intermediate_code_pc(env, tb);
>> @@ -228,8 +257,10 @@ static int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
>>
>> /* find opc index corresponding to search_pc */
>> tc_ptr = (uintptr_t)tb->tc_ptr;
>> - if (searched_pc < tc_ptr)
>> + if (searched_pc < tc_ptr) {
>> + tb_unlock();
>> return -1;
>> + }
>>
>> s->tb_next_offset = tb->tb_next_offset;
>> #ifdef USE_DIRECT_JUMP
>> @@ -241,8 +272,10 @@ static int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
>> #endif
>> j = tcg_gen_code_search_pc(s, (tcg_insn_unit *)tc_ptr,
>> searched_pc - tc_ptr);
>> - if (j < 0)
>> + if (j < 0) {
>> + tb_unlock();
>> return -1;
>> + }
>> /* now find start of instruction before */
>> while (s->gen_opc_instr_start[j] == 0) {
>> j--;
>> @@ -255,6 +288,8 @@ static int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
>> s->restore_time += profile_getclock() - ti;
>> s->restore_count++;
>> #endif
>> +
>> + tb_unlock();
>> return 0;
>> }
>>
>> @@ -672,6 +707,7 @@ static inline void code_gen_alloc(size_t tb_size)
>> CODE_GEN_AVG_BLOCK_SIZE;
>> tcg_ctx.tb_ctx.tbs =
>> g_malloc(tcg_ctx.code_gen_max_blocks * sizeof(TranslationBlock));
>> + qemu_mutex_init(&tcg_ctx.tb_ctx.tb_lock);
>> }
>>
>> /* Must be called before using the QEMU cpus. 'tb_size' is the size
>> @@ -696,16 +732,22 @@ bool tcg_enabled(void)
>> return tcg_ctx.code_gen_buffer != NULL;
>> }
>>
>> -/* Allocate a new translation block. Flush the translation buffer if
>> - too many translation blocks or too much generated code. */
>> +/*
>> + * Allocate a new translation block. Flush the translation buffer if
>> + * too many translation blocks or too much generated code.
>> + * tb_alloc is not thread safe but tb_gen_code is protected by a mutex so this
>> + * function is called only by one thread.
> maybe: "..is not thread safe but tb_gen_code is protected by tb_lock so
> only one thread calls it at a time."?
Yes.
>> + */
>> static TranslationBlock *tb_alloc(target_ulong pc)
>> {
>> - TranslationBlock *tb;
>> + TranslationBlock *tb = NULL;
>>
>> if (tcg_ctx.tb_ctx.nb_tbs >= tcg_ctx.code_gen_max_blocks ||
>> (tcg_ctx.code_gen_ptr - tcg_ctx.code_gen_buffer) >=
>> tcg_ctx.code_gen_buffer_max_size) {
>> - return NULL;
>> + tb = &tcg_ctx.tb_ctx.tbs[tcg_ctx.tb_ctx.nb_tbs++];
>> + tb->pc = pc;
>> + tb->cflags = 0;
>> }
>> tb = &tcg_ctx.tb_ctx.tbs[tcg_ctx.tb_ctx.nb_tbs++];
>> tb->pc = pc;
> That looks weird.
>
> if (cond) return
> &tcg_ctx.tb_ctx.tbs[tcg_ctx.tb_ctx.nb_tbs++] then return
> &tcg_ctx.tb_ctx.tbs[tcg_ctx.tb_ctx.nb_tbs++];?
>
> Also rendering the setting of tb = NULL pointless as it will always be
> from the array?
Oops yes sorry, this is definitely a mistake, those changes should have
disappeared.
Thanks,
Fred
>
>> @@ -718,11 +760,16 @@ void tb_free(TranslationBlock *tb)
>> /* In pr actice this is mostly used for single use temporary TB
>> Ignore the hard cases and just back up if this TB happens to
>> be the last one generated. */
>> +
>> + tb_lock();
>> +
>> if (tcg_ctx.tb_ctx.nb_tbs > 0 &&
>> tb == &tcg_ctx.tb_ctx.tbs[tcg_ctx.tb_ctx.nb_tbs - 1]) {
>> tcg_ctx.code_gen_ptr = tb->tc_ptr;
>> tcg_ctx.tb_ctx.nb_tbs--;
>> }
>> +
>> + tb_unlock();
>> }
>>
>> static inline void invalidate_page_bitmap(PageDesc *p)
>> @@ -773,6 +820,8 @@ void tb_flush(CPUArchState *env1)
>> {
>> CPUState *cpu = ENV_GET_CPU(env1);
>>
>> + tb_lock();
>> +
>> #if defined(DEBUG_FLUSH)
>> printf("qemu: flush code_size=%ld nb_tbs=%d avg_tb_size=%ld\n",
>> (unsigned long)(tcg_ctx.code_gen_ptr - tcg_ctx.code_gen_buffer),
>> @@ -797,6 +846,8 @@ void tb_flush(CPUArchState *env1)
>> /* XXX: flush processor icache at this point if cache flush is
>> expensive */
>> tcg_ctx.tb_ctx.tb_flush_count++;
>> +
>> + tb_unlock();
>> }
>>
>> #ifdef DEBUG_TB_CHECK
>> @@ -806,6 +857,8 @@ static void tb_invalidate_check(target_ulong address)
>> TranslationBlock *tb;
>> int i;
>>
>> + tb_lock();
>> +
>> address &= TARGET_PAGE_MASK;
>> for (i = 0; i < CODE_GEN_PHYS_HASH_SIZE; i++) {
>> for (tb = tb_ctx.tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
>> @@ -817,6 +870,8 @@ static void tb_invalidate_check(target_ulong address)
>> }
>> }
>> }
>> +
>> + tb_unlock();
>> }
>>
>> /* verify that all the pages have correct rights for code */
>> @@ -825,6 +880,8 @@ static void tb_page_check(void)
>> TranslationBlock *tb;
>> int i, flags1, flags2;
>>
>> + tb_lock();
>> +
>> for (i = 0; i < CODE_GEN_PHYS_HASH_SIZE; i++) {
>> for (tb = tcg_ctx.tb_ctx.tb_phys_hash[i]; tb != NULL;
>> tb = tb->phys_hash_next) {
>> @@ -836,6 +893,8 @@ static void tb_page_check(void)
>> }
>> }
>> }
>> +
>> + tb_unlock();
>> }
>>
>> #endif
>> @@ -916,6 +975,8 @@ void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr)
>> tb_page_addr_t phys_pc;
>> TranslationBlock *tb1, *tb2;
>>
>> + tb_lock();
>> +
>> /* remove the TB from the hash list */
>> phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
>> h = tb_phys_hash_func(phys_pc);
>> @@ -963,6 +1024,7 @@ void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr)
>> tb->jmp_first = (TranslationBlock *)((uintptr_t)tb | 2); /* fail safe */
>>
>> tcg_ctx.tb_ctx.tb_phys_invalidate_count++;
>> + tb_unlock();
>> }
>>
>> static void build_page_bitmap(PageDesc *p)
>> @@ -1004,6 +1066,8 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
>> target_ulong virt_page2;
>> int code_gen_size;
>>
>> + tb_lock();
>> +
>> phys_pc = get_page_addr_code(env, pc);
>> if (use_icount) {
>> cflags |= CF_USE_ICOUNT;
>> @@ -1032,6 +1096,8 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
>> phys_page2 = get_page_addr_code(env, virt_page2);
>> }
>> tb_link_page(tb, phys_pc, phys_page2);
>> +
>> + tb_unlock();
>> return tb;
>> }
>>
>> @@ -1330,13 +1396,15 @@ static inline void tb_alloc_page(TranslationBlock *tb,
>> }
>>
>> /* add a new TB and link it to the physical page tables. phys_page2 is
>> - (-1) to indicate that only one page contains the TB. */
>> + * (-1) to indicate that only one page contains the TB. */
>> static void tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
>> tb_page_addr_t phys_page2)
>> {
>> unsigned int h;
>> TranslationBlock **ptb;
>>
>> + tb_lock();
>> +
>> /* Grab the mmap lock to stop another thread invalidating this TB
>> before we are done. */
>> mmap_lock();
>> @@ -1370,6 +1438,8 @@ static void tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
>> tb_page_check();
>> #endif
>> mmap_unlock();
>> +
>> + tb_unlock();
>> }
>>
>> /* find the TB 'tb' such that tb[0].tc_ptr <= tc_ptr <
>> @@ -1378,31 +1448,34 @@ static TranslationBlock *tb_find_pc(uintptr_t tc_ptr)
>> {
>> int m_min, m_max, m;
>> uintptr_t v;
>> - TranslationBlock *tb;
>> -
>> - if (tcg_ctx.tb_ctx.nb_tbs <= 0) {
>> - return NULL;
>> - }
>> - if (tc_ptr < (uintptr_t)tcg_ctx.code_gen_buffer ||
>> - tc_ptr >= (uintptr_t)tcg_ctx.code_gen_ptr) {
>> - return NULL;
>> - }
>> - /* binary search (cf Knuth) */
>> - m_min = 0;
>> - m_max = tcg_ctx.tb_ctx.nb_tbs - 1;
>> - while (m_min <= m_max) {
>> - m = (m_min + m_max) >> 1;
>> - tb = &tcg_ctx.tb_ctx.tbs[m];
>> - v = (uintptr_t)tb->tc_ptr;
>> - if (v == tc_ptr) {
>> - return tb;
>> - } else if (tc_ptr < v) {
>> - m_max = m - 1;
>> - } else {
>> - m_min = m + 1;
>> + TranslationBlock *tb = NULL;
>> +
>> + tb_lock();
>> +
>> + if ((tcg_ctx.tb_ctx.nb_tbs > 0)
>> + && (tc_ptr >= (uintptr_t)tcg_ctx.code_gen_buffer &&
>> + tc_ptr < (uintptr_t)tcg_ctx.code_gen_ptr)) {
>> + /* binary search (cf Knuth) */
>> + m_min = 0;
>> + m_max = tcg_ctx.tb_ctx.nb_tbs - 1;
>> + while (m_min <= m_max) {
>> + m = (m_min + m_max) >> 1;
>> + tb = &tcg_ctx.tb_ctx.tbs[m];
>> + v = (uintptr_t)tb->tc_ptr;
>> + if (v == tc_ptr) {
>> + tb_unlock();
>> + return tb;
>> + } else if (tc_ptr < v) {
>> + m_max = m - 1;
>> + } else {
>> + m_min = m + 1;
>> + }
>> }
>> + tb = &tcg_ctx.tb_ctx.tbs[m_max];
>> }
>> - return &tcg_ctx.tb_ctx.tbs[m_max];
>> +
>> + tb_unlock();
>> + return tb;
>> }
>>
>> #if !defined(CONFIG_USER_ONLY)
>> @@ -1564,6 +1637,8 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf)
>> int direct_jmp_count, direct_jmp2_count, cross_page;
>> TranslationBlock *tb;
>>
>> + tb_lock();
>> +
>> target_code_size = 0;
>> max_target_code_size = 0;
>> cross_page = 0;
>> @@ -1619,6 +1694,8 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf)
>> tcg_ctx.tb_ctx.tb_phys_invalidate_count);
>> cpu_fprintf(f, "TLB flush count %d\n", tlb_flush_count);
>> tcg_dump_info(f, cpu_fprintf);
>> +
>> + tb_unlock();
>> }
>>
>> void dump_opcount_info(FILE *f, fprintf_function cpu_fprintf)
next prev parent reply other threads:[~2015-07-07 13:16 UTC|newest]
Thread overview: 82+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-06-26 14:47 [Qemu-devel] [RFC PATCH V6 00/18] Multithread TCG fred.konrad
2015-06-26 14:47 ` [Qemu-devel] [RFC PATCH V6 01/18] cpu: make cpu_thread_is_idle public fred.konrad
2015-07-07 9:47 ` Alex Bennée
2015-07-07 11:43 ` Frederic Konrad
2015-06-26 14:47 ` [Qemu-devel] [RFC PATCH V6 02/18] replace spinlock by QemuMutex fred.konrad
2015-07-07 10:15 ` Alex Bennée
2015-07-07 10:22 ` Paolo Bonzini
2015-07-07 11:48 ` Frederic Konrad
2015-07-07 12:34 ` Paolo Bonzini
2015-07-07 13:06 ` Frederic Konrad
2015-07-07 11:46 ` Frederic Konrad
2015-06-26 14:47 ` [Qemu-devel] [RFC PATCH V6 03/18] remove unused spinlock fred.konrad
2015-06-26 14:53 ` Paolo Bonzini
2015-06-26 15:29 ` Frederic Konrad
2015-06-26 15:46 ` Paolo Bonzini
2015-06-26 14:47 ` [Qemu-devel] [RFC PATCH V6 04/18] add support for spin lock on POSIX systems exclusively fred.konrad
2015-06-26 14:55 ` Paolo Bonzini
2015-06-26 15:31 ` Frederic Konrad
2015-06-26 14:47 ` [Qemu-devel] [RFC PATCH V6 05/18] protect TBContext with tb_lock fred.konrad
2015-06-26 14:56 ` Paolo Bonzini
2015-06-26 15:39 ` Frederic Konrad
2015-06-26 15:45 ` Paolo Bonzini
2015-06-26 16:20 ` Paolo Bonzini
2015-07-07 12:22 ` Alex Bennée
2015-07-07 13:16 ` Frederic Konrad [this message]
2015-06-26 14:47 ` [Qemu-devel] [RFC PATCH V6 06/18] tcg: remove tcg_halt_cond global variable fred.konrad
2015-06-26 15:02 ` Paolo Bonzini
2015-06-26 15:41 ` Frederic Konrad
2015-07-07 12:27 ` Alex Bennée
2015-07-07 13:17 ` Frederic Konrad
2015-06-26 14:47 ` [Qemu-devel] [RFC PATCH V6 07/18] Drop global lock during TCG code execution fred.konrad
2015-06-26 14:56 ` Jan Kiszka
2015-06-26 15:08 ` Paolo Bonzini
2015-06-26 15:36 ` Frederic Konrad
2015-06-26 15:42 ` Jan Kiszka
2015-06-26 16:11 ` Frederic Konrad
2015-07-07 12:33 ` Alex Bennée
2015-07-07 13:18 ` Frederic Konrad
2015-06-26 14:47 ` [Qemu-devel] [RFC PATCH V6 08/18] cpu: remove exit_request global fred.konrad
2015-06-26 15:03 ` Paolo Bonzini
2015-07-07 13:04 ` Alex Bennée
2015-07-07 13:25 ` Frederic Konrad
2015-06-26 14:47 ` [Qemu-devel] [RFC PATCH V6 09/18] cpu: add a tcg_executing flag fred.konrad
2015-07-07 13:23 ` Alex Bennée
2015-07-07 13:30 ` Frederic Konrad
2015-06-26 14:47 ` [Qemu-devel] [RFC PATCH V6 10/18] tcg: switch on multithread fred.konrad
2015-07-07 13:40 ` Alex Bennée
2015-06-26 14:47 ` [Qemu-devel] [RFC PATCH V6 11/18] cpus: make qemu_cpu_kick_thread public fred.konrad
2015-07-07 15:11 ` Alex Bennée
2015-06-26 14:47 ` [Qemu-devel] [RFC PATCH V6 12/18] Use atomic cmpxchg to atomically check the exclusive value in a STREX fred.konrad
2015-06-26 14:47 ` [Qemu-devel] [RFC PATCH V6 13/18] cpu: introduce async_run_safe_work_on_cpu fred.konrad
2015-06-26 15:35 ` Paolo Bonzini
2015-06-26 16:09 ` Frederic Konrad
2015-06-26 16:23 ` Paolo Bonzini
2015-06-26 16:36 ` Frederic Konrad
2015-06-26 14:47 ` [Qemu-devel] [RFC PATCH V6 14/18] add a callback when tb_invalidate is called fred.konrad
2015-06-26 16:20 ` Paolo Bonzini
2015-06-26 16:40 ` Frederic Konrad
2015-07-07 15:32 ` Alex Bennée
2015-06-26 14:47 ` [Qemu-devel] [RFC PATCH V6 15/18] cpu: introduce tlb_flush*_all fred.konrad
2015-06-26 15:15 ` Paolo Bonzini
2015-06-26 15:54 ` Frederic Konrad
2015-06-26 16:01 ` Paolo Bonzini
2015-06-26 16:08 ` Peter Maydell
2015-06-26 16:30 ` Frederic Konrad
2015-06-26 16:31 ` Paolo Bonzini
2015-06-26 16:35 ` Frederic Konrad
2015-06-26 16:39 ` Paolo Bonzini
2015-07-06 14:29 ` Mark Burton
2015-07-07 16:12 ` Alex Bennée
2015-06-26 16:54 ` Paolo Bonzini
2015-07-08 15:35 ` Frederic Konrad
2015-07-07 15:52 ` Alex Bennée
2015-06-26 14:47 ` [Qemu-devel] [RFC PATCH V6 16/18] arm: use tlb_flush*_all fred.konrad
2015-07-07 16:14 ` Alex Bennée
2015-06-26 14:47 ` [Qemu-devel] [RFC PATCH V6 17/18] translate-all: introduces tb_flush_safe fred.konrad
2015-07-07 16:16 ` Alex Bennée
2015-06-26 14:47 ` [Qemu-devel] [RFC PATCH V6 18/18] translate-all: (wip) use tb_flush_safe when we can't alloc more tb fred.konrad
2015-06-26 16:21 ` Paolo Bonzini
2015-06-26 16:38 ` Frederic Konrad
2015-07-07 16:17 ` Alex Bennée
2015-07-07 16:23 ` Frederic Konrad
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=559BD13B.4080804@greensocs.com \
--to=fred.konrad@greensocs.com \
--cc=a.spyridakis@virtualopensystems.com \
--cc=agraf@suse.de \
--cc=alex.bennee@linaro.org \
--cc=alistair.francis@xilinx.com \
--cc=guillaume.delbergue@greensocs.com \
--cc=mark.burton@greensocs.com \
--cc=mttcg@listserver.greensocs.com \
--cc=pbonzini@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.