qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PULL 04/13] target-i386: Re-introduce optimal breakpoint r


From: Eduardo Habkost
Subject: [Qemu-devel] [PULL 04/13] target-i386: Re-introduce optimal breakpoint removal
Date: Fri, 23 Oct 2015 13:33:03 -0200

From: Richard Henderson <address@hidden>

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: Richard Henderson <address@hidden>
Signed-off-by: Paolo Bonzini <address@hidden>
Signed-off-by: Eduardo Habkost <address@hidden>
---
 target-i386/bpt_helper.c | 34 ++++++++++++++++++++++++++++------
 1 file changed, 28 insertions(+), 6 deletions(-)

diff --git a/target-i386/bpt_helper.c b/target-i386/bpt_helper.c
index f14788a..23ce828 100644
--- a/target-i386/bpt_helper.c
+++ b/target-i386/bpt_helper.c
@@ -82,14 +82,36 @@ 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;
 
-    for (i = 0; i < DR7_MAX_BP; i++) {
-        hw_breakpoint_remove(env, i);
-    }
-    env->dr[7] = new_dr7;
-    for (i = 0; i < DR7_MAX_BP; i++) {
-        hw_breakpoint_insert(env, 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);
+        }
+        env->dr[7] = new_dr7;
+        for (i = 0; i < DR7_MAX_BP; i++) {
+            hw_breakpoint_insert(env, i);
+        }
     }
 }
 #endif
-- 
2.1.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]