Commit 36eb6e09 authored by Richard Henderson's avatar Richard Henderson Committed by Eduardo Habkost
Browse files

target-i386: Re-introduce optimal breakpoint removal



Before the last patch, we had an efficient loop that disabled
local breakpoints on task switch.  Re-add that, but in a more
general way that handles changes to the global enable bits too.

Signed-off-by: default avatarRichard Henderson <rth@twiddle.net>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
Signed-off-by: default avatarEduardo Habkost <ehabkost@redhat.com>
parent 93d00d0f
Loading
Loading
Loading
Loading
+28 −6
Original line number Diff line number Diff line
@@ -82,8 +82,29 @@ static void hw_breakpoint_remove(CPUX86State *env, int index)

void cpu_x86_update_dr7(CPUX86State *env, uint32_t new_dr7)
{
    target_ulong old_dr7 = env->dr[7];
    int i;

    /* If nothing is changing except the global/local enable bits,
       then we can make the change more efficient.  */
    if (((old_dr7 ^ new_dr7) & ~0xff) == 0) {
        /* Fold the global and local enable bits together into the
           global fields, then xor to show which registers have
           changed collective enable state.  */
        int mod = ((old_dr7 | old_dr7 * 2) ^ (new_dr7 | new_dr7 * 2)) & 0xff;

        for (i = 0; i < DR7_MAX_BP; i++) {
            if ((mod & (2 << i * 2)) && !hw_breakpoint_enabled(new_dr7, i)) {
                hw_breakpoint_remove(env, i);
            }
        }
        env->dr[7] = new_dr7;
        for (i = 0; i < DR7_MAX_BP; i++) {
            if (mod & (2 << i * 2) && hw_breakpoint_enabled(new_dr7, i)) {
                hw_breakpoint_insert(env, i);
            }
        }
    } else {
        for (i = 0; i < DR7_MAX_BP; i++) {
            hw_breakpoint_remove(env, i);
        }
@@ -92,6 +113,7 @@ void cpu_x86_update_dr7(CPUX86State *env, uint32_t new_dr7)
            hw_breakpoint_insert(env, i);
        }
    }
}
#endif

static bool check_hw_breakpoints(CPUX86State *env, bool force_dr6_update)