On Tue, Jan 17, 2012 at 7:03 PM, 陳韋任 <che...@iis.sinica.edu.tw> wrote: >> 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
Chenwj, you are correct, the check bypasses the whole function, I was not paying enough attention to that check, it should never be null, in which case the code doesn't get executed and the chaining remains unchanged. Thanks. -Jim