]> Zhao Yanbai Git Server - minix.git/commitdiff
arm: recognize instruction fetch pagefault 68/568/1
authorBen Gras <ben@minix3.org>
Tue, 21 May 2013 12:57:57 +0000 (14:57 +0200)
committerBen Gras <ben@minix3.org>
Tue, 21 May 2013 13:05:06 +0000 (15:05 +0200)
. an instruction fetch pagefault generates a prefetch
  abort exception, this should also be a source of
  a pagefault event
. the saved_lr argument to the C exception handler was
  sometimes an address, sometimes a pointer to that address;
  the kernel sometimes dereferences it, so it should always be
  an in-kernel address, never a userspace address. fix in mpx.S
  makes it always a pointer.
. move dumping of all processes over serial out of
  the arch-specific arch_system.c

kernel/arch/earm/exception.c
kernel/arch/earm/mpx.S
kernel/arch/i386/arch_system.c
kernel/proc.c

index 2a2ca0f14ec456abcf9b05a226918a244e07c7b9..84b4fe62a6e9d6babc0dc35dc7e6fc8dd34970c7 100644 (file)
@@ -37,22 +37,15 @@ static void proc_stacktrace_execute(struct proc *whichproc, reg_t v_bp, reg_t pc
 
 static void pagefault( struct proc *pr,
                        reg_t *saved_lr,
-                       int is_nested)
+                       int is_nested,
+                       u32_t pagefault_addr,
+                       u32_t pagefault_status)
 {
        int in_physcopy = 0, in_memset = 0;
 
-       reg_t pagefault_addr, pagefault_status;
        message m_pagefault;
        int err;
 
-       pagefault_addr = read_dfar();
-       pagefault_status = read_dfsr();
-
-#if 0
-       printf("kernel: pagefault in pr %d, addr 0x%lx, his ttbr 0x%lx, actual ttbr 0x%lx\n",
-               pr->p_endpoint, pagefault_addr, pr->p_seg.p_ttbr, read_ttbr0());
-#endif
-
        in_physcopy = (*saved_lr > (vir_bytes) phys_copy) &&
           (*saved_lr < (vir_bytes) phys_copy_fault);
 
@@ -61,9 +54,6 @@ static void pagefault( struct proc *pr,
 
        if((is_nested || iskernelp(pr)) &&
                catch_pagefaults && (in_physcopy || in_memset)) {
-#if 0
-               printf("pf caught! addr 0x%lx\n", pagefault_addr);
-#endif
                if (is_nested) {
                        if(in_physcopy) {
                                assert(!in_memset);
@@ -153,6 +143,8 @@ void exception_handler(int is_nested, reg_t *saved_lr, int vector)
 
   ep = &ex_data[vector];
 
+  assert((vir_bytes) saved_lr >= kinfo.vir_kern_start);
+
   /*
    * handle special cases for nested problems as they might be tricky or filter
    * them out quickly if the traps are not nested
@@ -179,7 +171,22 @@ void exception_handler(int is_nested, reg_t *saved_lr, int vector)
   }
 
   if (vector == DATA_ABORT_VECTOR) {
-       pagefault(saved_proc, saved_lr, is_nested);
+       pagefault(saved_proc, saved_lr, is_nested, read_dfar(), read_dfsr());
+       return;
+  }
+
+  if (!is_nested && vector == PREFETCH_ABORT_VECTOR) {
+       reg_t ifar = read_ifar(), ifsr = read_ifsr();
+
+       /* The saved_lr is the instruction we're going to execute after
+        * the fault is handled; IFAR is the address that pagefaulted
+        * while fetching the instruction. As far as we know the two
+        * should be the same, if not this assumption will lead to very
+        * hard to debug problems (instruction executing being off by one)
+        * and this assumption needs re-examining, hence the assert.
+        */
+       assert(*saved_lr == ifar);
+       pagefault(saved_proc, saved_lr, is_nested, ifar, ifsr);
        return;
   }
 
index 622bc83f9c9313ba4bc8be86c2291a23f0f27464..dba2b8446ce0aa1946e75f69a93f9ae1ee4eb782 100644 (file)
@@ -83,7 +83,7 @@ ENTRY(\exc_name\()_entry)
        /* save the pointer to the current process */
        ldr     fp, [sp]
        /* save the exception pc (saved lr_user) */
-       ldr     r4, [fp, #PCREG]
+       add     r4, fp, #PCREG
 
        /* stop user process cycles */
        mov     r0, fp  /* first param: caller proc ptr */
index 2c5e0931e7431f927b44c47b8145d4264267da52..bb12b0682d679c5813193d3f761a77b68409313c 100644 (file)
@@ -421,17 +421,6 @@ static void ser_debug(const int c)
 }
 
 #if DEBUG_SERIAL
-void ser_dump_proc()
-{
-       struct proc *pp;
-
-       for (pp= BEG_PROC_ADDR; pp < END_PROC_ADDR; pp++)
-       {
-               if (isemptyp(pp))
-                       continue;
-               print_proc_recursive(pp);
-       }
-}
 
 static void ser_dump_vfs()
 {
index a150393154eb2eb2bda1bb563676f410affe47b9..e60e550717591b0de5ebc59cccbc91772b59a927 100644 (file)
@@ -1894,3 +1894,15 @@ void release_fpu(struct proc * p) {
        if (*fpu_owner_ptr == p)
                *fpu_owner_ptr = NULL;
 }
+
+void ser_dump_proc()
+{
+        struct proc *pp;
+
+        for (pp= BEG_PROC_ADDR; pp < END_PROC_ADDR; pp++)
+        {
+                if (isemptyp(pp))
+                        continue;
+                print_proc_recursive(pp);
+        }
+}