On 08/18/2011 04:31 AM, Max Filippov wrote: >> Hi, all >> >> I am trying to figure out why QEMU put some constraints on block >> linking (chaining). Take x86 as an example, there are two places >> put constraints on block linking, gen_goto_tb and cpu_exec. >> >> ----------------- gen_goto_tb (target-i386/translate.c) --------------- >> /* NOTE: we handle the case where the TB spans two pages here */ >> if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) || >> (pc & TARGET_PAGE_MASK) == ((s->pc - 1) & TARGET_PAGE_MASK)) { >> /* jump to same page: we can use a direct jump */ >> tcg_gen_goto_tb(tb_num); >> gen_jmp_im(eip); >> tcg_gen_exit_tb((tcg_target_long)tb + tb_num); >> } else { >> /* jump to another page: currently not optimized */ >> gen_jmp_im(eip); >> gen_eob(s); >> } >> ----------------------------------------------------------------------- >> >> ----------------------- cpu_exec (cpu-exec.c) ------------------------- >> /* see if we can patch the calling TB. When the TB >> spans two pages, we cannot safely do a direct >> jump. */ >> if (next_tb != 0 && tb->page_addr[1] == -1) { >> tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb); >> } >> ----------------------------------------------------------------------- >> >> Is it just because we cannot optimize block linking which crosses page >> boundary, or there are some correctness/safety issues should be considered? > > If we link a TB with another TB from the different page, then the > second TB may disappear when the memory mapping changes and the > subsequent direct jump from the first TB will crash qemu. > > I guess that this usually does not happen in usermode, because the > guest would not modify executable code memory mapping. However I > suppose that this is also possible.
Dynamic linking modifies guest code, requiring the page to be retranslated. With lazy binding this can happen at any time, and without PIE executables this can happen to just about any executable page. Rob