qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH 4/8] target-i386: Re-introduce optimal breakpoint re


From: Richard Henderson
Subject: [Qemu-devel] [PATCH 4/8] target-i386: Re-introduce optimal breakpoint removal
Date: Tue, 15 Sep 2015 11:45:09 -0700

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>
---
 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..911d9f8 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)) {
+                /* We know that register i has changed enable state;
+                   recheck what that state should be and apply.  */
+                if (hw_breakpoint_enabled(new_dr7, i)) {
+                    hw_breakpoint_insert(env, i);
+                } else {
+                    hw_breakpoint_remove(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]