• S
    cputlb: Fix for self-modifying writes across page boundaries · 81daabaf
    Samuel Damashek 提交于
    As it currently stands, QEMU does not properly handle self-modifying code
    when the write is unaligned and crosses a page boundary. The procedure
    for handling a write to the current translation block is to write-protect
    the current translation block, catch the write, split up the translation
    block into the current instruction (which remains write-protected so that
    the current instruction is not modified) and the remaining instructions
    in the translation block, and then restore the CPU state to before the
    write occurred so the write will be retried and successfully executed.
    However, since unaligned writes across pages are split into one-byte
    writes for simplicity, writes to the second page (which is not the
    current TB) may succeed before a write to the current TB is attempted,
    and since these writes are not invalidated before resuming state after
    splitting the TB, these writes will be performed a second time, thus
    corrupting the second page. Credit goes to Patrick Hulin for
    discovering this.
    
    In recent 64-bit versions of Windows running in emulated mode, this
    results in either being very unstable (a BSOD after a couple minutes of
    uptime), or being entirely unable to boot. Windows performs one or more
    8-byte unaligned self-modifying writes (xors) which intersect the end
    of the current TB and the beginning of the next TB, which runs into the
    aforementioned issue. This commit fixes that issue by making the
    unaligned write loop perform the writes in forwards order, instead of
    reverse order. This way, QEMU immediately tries to write to the current
    TB, and splits the TB before any write to the second page is executed.
    The write then proceeds as intended. With this patch applied, I am able
    to boot and use Windows 7 64-bit and Windows 10 64-bit in QEMU without
    KVM.
    
    Per Richard Henderson's input, this patch also ensures the second page
    is in the TLB before executing the write loop, to ensure the second
    page is mapped.
    
    The original discussion of the issue is located at
    http://lists.nongnu.org/archive/html/qemu-devel/2014-08/msg02161.html.
    Signed-off-by: NSamuel Damashek <samuel.damashek@invincea.com>
    Message-Id: <20160706182652.16190-1-samuel.damashek@invincea.com>
    Signed-off-by: NRichard Henderson <rth@twiddle.net>
    81daabaf
softmmu_template.h 18.6 KB