瀏覽代碼

CPU: Handle Debug exception

We currently only care about debug exceptions that are triggered
by the single-step execution mode.

The debug exception is translated to a SIGTRAP, which can be caught
and handled by the tracing thread.
Itamar 5 年之前
父節點
當前提交
d04409b444
共有 2 個文件被更改,包括 32 次插入3 次删除
  1. 30 3
      Kernel/Arch/i386/CPU.cpp
  2. 2 0
      Kernel/Arch/i386/CPU.h

+ 30 - 3
Kernel/Arch/i386/CPU.cpp

@@ -297,11 +297,31 @@ void page_fault_handler(RegisterState regs)
     }
     }
 }
 }
 
 
+EH_ENTRY_NO_CODE(1, debug);
+void debug_handler(RegisterState regs)
+{
+    clac();
+    if (!Process::current || (regs.cs & 3) == 0) {
+        klog() << "Debug Exception in Ring0";
+        hang();
+        return;
+    }
+    constexpr u8 REASON_SINGLESTEP = 14;
+    bool is_reason_singlestep = (read_dr6() & (1 << REASON_SINGLESTEP));
+    if (!is_reason_singlestep)
+        return;
+
+    if (Thread::current->tracer()) {
+        Thread::current->tracer()->set_regs(regs);
+    }
+    Thread::current->send_urgent_signal_to_self(SIGTRAP);
+}
+
 EH_ENTRY_NO_CODE(3, breakpoint);
 EH_ENTRY_NO_CODE(3, breakpoint);
 void breakpoint_handler(RegisterState regs)
 void breakpoint_handler(RegisterState regs)
 {
 {
     clac();
     clac();
-    if (!Process::current || Process::current->is_ring0()) {
+    if (!Process::current || (regs.cs & 3) == 0) {
         klog() << "Breakpoint Trap in Ring0";
         klog() << "Breakpoint Trap in Ring0";
         hang();
         hang();
         return;
         return;
@@ -329,7 +349,6 @@ void breakpoint_handler(RegisterState regs)
         hang();                                                                                                                                                                \
         hang();                                                                                                                                                                \
     }
     }
 
 
-EH(1, "Debug exception")
 EH(2, "Unknown error")
 EH(2, "Unknown error")
 EH(4, "Overflow")
 EH(4, "Overflow")
 EH(5, "Bounds check")
 EH(5, "Bounds check")
@@ -498,7 +517,7 @@ void idt_init()
         register_interrupt_handler(i, unimp_trap);
         register_interrupt_handler(i, unimp_trap);
 
 
     register_interrupt_handler(0x00, divide_error_asm_entry);
     register_interrupt_handler(0x00, divide_error_asm_entry);
-    register_interrupt_handler(0x01, _exception1);
+    register_user_callable_interrupt_handler(0x01, debug_asm_entry);
     register_interrupt_handler(0x02, _exception2);
     register_interrupt_handler(0x02, _exception2);
     register_user_callable_interrupt_handler(0x03, breakpoint_asm_entry);
     register_user_callable_interrupt_handler(0x03, breakpoint_asm_entry);
     register_interrupt_handler(0x04, _exception4);
     register_interrupt_handler(0x04, _exception4);
@@ -828,6 +847,14 @@ void write_cr3(u32 cr3)
                  : "memory");
                  : "memory");
 }
 }
 
 
+u32 read_dr6()
+{
+    u32 dr6;
+    asm("movl %%dr6, %%eax"
+        : "=a"(dr6));
+    return dr6;
+}
+
 }
 }
 
 
 #ifdef DEBUG
 #ifdef DEBUG

+ 2 - 0
Kernel/Arch/i386/CPU.h

@@ -480,6 +480,8 @@ inline FlatPtr offset_in_page(const void* address)
 u32 read_cr3();
 u32 read_cr3();
 void write_cr3(u32);
 void write_cr3(u32);
 
 
+u32 read_dr6();
+
 class CPUID {
 class CPUID {
 public:
 public:
     CPUID(u32 function) { asm volatile("cpuid"
     CPUID(u32 function) { asm volatile("cpuid"