> 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