qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] icount and tb chaining


From: 陳韋任
Subject: Re: [Qemu-devel] icount and tb chaining
Date: Wed, 18 Jan 2012 11:03:33 +0800
User-agent: Mutt/1.5.21 (2010-09-15)

> if (!tb->jmp_next[n]) { <--- what if n is 2?
> 
> This is my question, if n is two, it would actually be checking the
> jmp_first field immediatedly following the jmp_next array in the tb
> structure.  This function only updates the jmp_first field and doesn't
> touch jmp_next when n is 2. Does anybody know why this is? It seems
> like you would like to leave the tb chaining as it was, because you
> are going to execute the same translation block again, it just jumped
> out to replenish the icount_decr counter. -Jim

  I set a conditional breakpoint at tb_add_jump to watch what happened when
n is 2. Look at tb_link_page (exec.c) first, which initializes some fields of
a TranslatioBlock.

void tb_link_page(TranslationBlock *tb, ...)
{
    tb->jmp_first = (TranslationBlock *)((long)tb | 2);
    tb->jmp_next[0] = NULL;
    tb->jmp_next[1] = NULL;
}

  And look at struct TranslationBlock (exec-all.h),

struct TranslationBlock {
    /* list of TBs jumping to this one. This is a circular list using
       the two least significant bits of the pointers to tell what is
       the next pointer: 0 = jmp_next[0], 1 = jmp_next[1], 2 =
       jmp_first */
    struct TranslationBlock *jmp_next[2];
    struct TranslationBlock *jmp_first;
}

I think those numbers (0, 1, and 2) means tb_add_jump 2nd parameter here, so
it's intentionally to check jmp_first when n is 2. Since tb->jmp_first is never
to be zero, then condition is always false (do nothing) when n is 2. You said

  "This function only updates the jmp_first field and doesn't touch jmp_next
   when n is 2"

Do you mean in some case (tb->jmp_first == 0) it might execute the following
code when n is 2? Because I don't see tb_add_jump updates jmp_first and leave
jmp_next alone when n is 2, it just do nothing.

    tb_set_jmp_target(tb, n, (unsigned long)tb_next->tc_ptr);
    tb->jmp_next[n] = tb_next->jmp_first;
    tb_next->jmp_first = (TranslationBlock *)((long)(tb) | (n));

Your guess makes sense to me,

  "It seems like you would like to leave the tb chaining as it was, because you
   are going to execute the same translation block again, it just jumped out to
   replenish the icount_decr counter"

And talk about the meaning of last significant bits of TranslationBlock*. AFAIK,
if last significant bits of TranslationBlock* are set to 2, then it means the
circular list of block chaining is stopped at this TranslationBlock. For
example, if tb1 links to tb2 (tb1 -> tb2), then

  tb1->jmp_next = tb2 | 2
  tb2->jmp_first = tb1 | 1

You can check the slide below if you want. It illustates how those fields
(jmp_first and jmp_next) are used in block chaining.

  http://www.hellogcc.org/wp-content/uploads/2011/10/QEMU-block-chaining.ppt

Regards,
chenwj
 
-- 
Wei-Ren Chen (陳韋任)
Computer Systems Lab, Institute of Information Science,
Academia Sinica, Taiwan (R.O.C.)
Tel:886-2-2788-3799 #1667
Homepage: http://people.cs.nctu.edu.tw/~chenwj



reply via email to

[Prev in Thread] Current Thread [Next in Thread]