Quellcode durchsuchen

fix

interrupt handler: return after handling faults
vaddr_range: use __parse_pse when encounter non present page tables
elf32_load: __user_push_string32 ailgn stack
greatbridf vor 9 Monaten
Ursprung
Commit
6734968dc6
3 geänderte Dateien mit 50 neuen und 33 gelöschten Zeilen
  1. 45 28
      src/kernel/interrupt.cpp
  2. 3 3
      src/kernel/mem/paging.cc
  3. 2 2
      src/types/elf.cpp

+ 45 - 28
src/kernel/interrupt.cpp

@@ -96,34 +96,36 @@ void kernel::irq::register_handler(int irqno, irq_handler_t handler)
     s_irq_handlers[irqno].emplace_back(std::move(handler));
 }
 
-extern "C" void interrupt_handler(
-        interrupt_stack_head* context,
+static inline void fault_handler(
+        interrupt_stack_with_code* context,
         mmx_registers* mmxregs)
 {
-    // interrupt is a fault
-    if (context->int_no < 0x20) {
-        auto* with_code = (interrupt_stack_with_code*)context;
-
-        switch (context->int_no) {
-        case 6:
-        case 8: {
-            if (!current_process->attr.system)
-                kill_current(SIGSEGV); // noreturn
-        } break;
-        case 13: {
-            if (!current_process->attr.system)
-                kill_current(SIGILL); // noreturn
-        } break;
-        case 14: {
-            kernel::mem::paging::handle_page_fault(with_code->error_code);
-            context->int_no = (unsigned long)context + 0x88;
-        }
-        }
-        freeze();
+    switch (context->head.int_no) {
+    case 6:
+    case 8: {
+        if (!current_process->attr.system)
+            kill_current(SIGSEGV); // noreturn
+    } break;
+    case 13: {
+        if (!current_process->attr.system)
+            kill_current(SIGILL); // noreturn
+    } break;
+    case 14: {
+        kernel::mem::paging::handle_page_fault(context->error_code);
+        context->head.int_no = (unsigned long)context + 0x88;
+        return;
+    } break;
     }
-    auto* real_context = (interrupt_stack_normal*)context;
 
-    int irqno = context->int_no - 0x20;
+    // fault can not be resolved
+    freeze();
+}
+
+static inline void irq_handler(
+        interrupt_stack_normal* context,
+        mmx_registers* mmxregs)
+{
+    int irqno = context->head.int_no - 0x20;
 
     constexpr uint8_t PIC_EOI = 0x20;
 
@@ -134,9 +136,24 @@ extern "C" void interrupt_handler(
     for (const auto& handler : s_irq_handlers[irqno])
         handler();
 
-    if (real_context->cs == 0x1b && current_thread->signals.pending_signal())
-        current_thread->signals.handle(real_context, mmxregs);
+    // syscall by int 0x80
+    if (context->cs == 0x1b && current_thread->signals.pending_signal())
+        current_thread->signals.handle(context, mmxregs);
 
-    context->int_no = (unsigned long)context + 0x80;
-    return;
+    context->head.int_no = (unsigned long)context + 0x80;
+}
+
+extern "C" void interrupt_handler(
+        interrupt_stack_head* context,
+        mmx_registers* mmxregs)
+{
+    // interrupt is a fault
+    if (context->int_no < 0x20) {
+        auto* with_code = (interrupt_stack_with_code*)context;
+        fault_handler(with_code, mmxregs);
+    }
+    else {
+        auto* normal = (interrupt_stack_normal*)context;
+        irq_handler(normal, mmxregs);
+    }
 }

+ 3 - 3
src/kernel/mem/paging.cc

@@ -395,13 +395,13 @@ vaddr_range& vaddr_range::operator++()
             // if idx4 is 0 after update, we have an overflow
             assert(idx4 != 0);
 
-            pdpt = pml4[idx4];
+            pdpt = __parse_pse(pml4[idx4], is_privilege);
         } while (false);
 
-        pd = pdpt[idx3];
+        pd = __parse_pse(pdpt[idx3], is_privilege);
     } while (false);
 
-    pt = pd[idx2];
+    pt = __parse_pse(pd[idx2], is_privilege);
     return *this;
 }
 

+ 2 - 2
src/types/elf.cpp

@@ -25,7 +25,7 @@ static inline void __user_push_string32(uintptr_t* sp, const char* str)
     size_t len = strlen(str);
 
     *sp -= (len + 1);
-    *sp &= 0xf; // align to 16 bytes
+    *sp &= ~0xf; // align to 16 bytes
 
     memcpy((void*)*sp, str, len + 1);
 }
@@ -95,7 +95,7 @@ int types::elf::elf32_load(types::elf::elf32_load_data& d)
             mm_list::map_args args{};
 
             args.vaddr = vaddr;
-            args.length = phent.filesz + (phent.vaddr & 0xfff);
+            args.length = flen;
             args.file_inode = exec->ind;
             args.file_offset = fileoff;