On Thu, Nov 24, 2011 at 08:54:36PM -0500, Xin Tong wrote: > I came back to the block chaining code. This code is still not very > clear to me. Here we are linking tb_next -> tb. jmp_next of the tb > contains the next tbs it will jump to. why are we checking the > !tb->jmp_next[n], but not !tb_next->jmp_next[n] ? > > static inline void tb_add_jump(TranslationBlock *tb, int n, > TranslationBlock *tb_next) > { > if (!tb->jmp_next[n]) { > /* patch the native jump address */ > tb_set_jmp_target(tb, n, (unsigned long)tb_next->tc_ptr); > > /* add in TB jmp circular list */ > tb->jmp_next[n] = tb_next->jmp_first; > tb_next->jmp_first = (TranslationBlock *)((long)(tb) | (n)); > } > }
Maybe I talked about TB chaining wrong before. The variable names in QEMU could be misleading. next_tb and tb_next are _different_ things. Let's see cpu_exec (cpu-exec.c) which calls tb_add_jump first. // TB chaining direction: next_tb -> tb if (next_tb != 0 && tb->page_addr[1] == -1) { tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb); } Then let's see tb_add_jump. // TB chaining direction: tb -> tb_next static inline void tb_add_jump(TranslationBlock *tb, int n, TranslationBlock *tb_next) { if (!tb->jmp_next[n]) { /* patch the native jump address */ tb_set_jmp_target(tb, n, (unsigned long)tb_next->tc_ptr); /* add in TB jmp circular list */ tb->jmp_next[n] = tb_next->jmp_first; tb_next->jmp_first = (TranslationBlock *)((long)(tb) | (n)); } } QEMU uses jmp_next and jmp_first to record the TB chaining status. I think visual presentation can help you understand how this is working. Here you go, http://people.cs.nctu.edu.tw/~chenwj/slide/QEMU/QEMU%20-%20block%20chaining.ppt P.S. In case you know chinese, you can see the articles on http://www.hellogcc.org/ (search tag qemu). 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