Port-amd64 archive

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

help needed for creating a patch for NetBSD-4



Hi,

I've been trying to create a patch for NetBSD-4 from the patch in here:
http://releng.netbsd.org/cgi-bin/req-5.cgi?show=1772

I got something that compiles (which is better than I expected), but
panics when booting:

com1 at isa0 port 0x2f8-0x2ff irq 3: ns16550a, working fifo
ioapic0: enabling
timecounter: Timecounter "clockinterrupt" frequency 100 Hz quality 0
Kernelized RAIDframe activated
uvm_fault(0xffffffff80b281c0, 0x0, 1) -> e
kernel: page fault trap, code=0
Stopped in pid 10.1 (atabus0) at        netbsd:Xintr_lapic_ltimer+0x7c: movl 
%gs:0x1f4(%rip),%ebx
db> bt
Xintr_lapic_ltimer() at netbsd:Xintr_lapic_ltimer+0x7c
--- interrupt ---
0:
db> sh reg
ds          0
es          0
fs          0
gs          0
rdi         0
rsi         0x280000
rbp         0xffff80004914fd00
rbx         0xffff800004ac0000
rdx         0x10
rcx         0x10
rax         0x2
r8          0
r9          0
r10         0xffffffff80c24db0  _prop_dictionary_keysym32_pool+0xf4c70
r11         0x1
r12         0xffffff01
r13         0x2750
r14         0x1
r15         0xffff800004ace210
rip         0xffffffff801010cc  Xintr_lapic_ltimer+0x7c
cs          0x8
rflags      0x10002
rsp         0xffff80004914fbd0
ss          0x10
netbsd:Xintr_lapic_ltimer+0x7c: movl    %gs:0x1f4(%rip),%ebx

Ideas? Enlightenment? Fixes? :)

regards,
        spz
Index: sys/arch/amd64/amd64/trap.c
===================================================================
RCS file: /cvsroot/src/sys/arch/amd64/amd64/trap.c,v
retrieving revision 1.27
diff -u -p -r1.27 trap.c
--- sys/arch/amd64/amd64/trap.c 23 Jul 2006 22:06:04 -0000      1.27
+++ sys/arch/amd64/amd64/trap.c 12 Jun 2012 22:36:16 -0000
@@ -120,6 +120,7 @@ __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.2
 #endif
 
 void trap __P((struct trapframe *));
+void trap_return_fault_return(struct trapframe *) __dead;
 #if defined(I386_CPU)
 int trapwrite __P((unsigned));
 #endif
@@ -178,16 +179,11 @@ trap(frame)
        struct proc *p = l ? l->l_proc : 0;
        int type = (int)frame->tf_trapno;
        struct pcb *pcb;
-       extern char fusuintrfailure[],
-                   resume_iret[];
+       extern char fusuintrfailure[];
 #if defined(COMPAT_10) || defined(COMPAT_IBCS2)
        extern char IDTVEC(oosyscall)[];
 #endif
-#if 0
-       extern char resume_pop_ds[], resume_pop_es[];
-#endif
        struct trapframe *vframe;
-       void *resume;
        caddr_t onfault;
        int error;
        uint64_t cr2;
@@ -268,50 +264,67 @@ copyfault:
 
                /*
                 * Check for failure during return to user mode.
+                * This can happen loading invalid values into the segment
+                * registers, or during the 'iret' itself.
                 *
-                * XXXfvdl check for rex prefix?
-                *
-                * We do this by looking at the instruction we faulted on.  The
-                * specific instructions we recognize only happen when
+                * We do this by looking at the instruction we faulted on.
+                * The specific instructions we recognize only happen when
                 * returning from a trap, syscall, or interrupt.
-                *
-                * XXX
-                * The heuristic used here will currently fail for the case of
-                * one of the 2 pop instructions faulting when returning from a
-                * a fast interrupt.  This should not be possible.  It can be
-                * fixed by rearranging the trap frame so that the stack format
-                * at this point is the same as on exit from a `slow'
-                * interrupt.
                 */
-               switch (*(u_char *)frame->tf_rip) {
-               case 0xcf:      /* iret */
-                       vframe = (void *)((u_int64_t)&frame->tf_rsp - 44);
-                       resume = resume_iret;
-                       break;
-/*
- * XXXfvdl these are illegal in long mode (not in compat mode, though)
- * and we do not take back the descriptors from the signal context anyway,
- * but may do so later for USER_LDT, in which case we need to intercept
- * other instructions (movl %eax, %Xs).
- */
-#if 0
-               case 0x1f:      /* popl %ds */
-                       vframe = (void *)((u_int64_t)&frame->tf_rsp - 4);
-                       resume = resume_pop_ds;
-                       break;
-               case 0x07:      /* popl %es */
-                       vframe = (void *)((u_int64_t)&frame->tf_rsp - 0);
-                       resume = resume_pop_es;
+
+kernelfault:
+               KSI_INIT_TRAP(&ksi);
+               ksi.ksi_signo = SIGSEGV;
+               ksi.ksi_code = SEGV_ACCERR;
+               ksi.ksi_trap = type;
+
+               /* Get %rsp value before fault - there may be a pad word
+                * below the trap frame. */
+               vframe = (void *)frame->tf_rsp;
+               switch (*(uint16_t *)frame->tf_rip) {
+               case 0xcf48:    /* iretq */
+                       /*
+                        * The 'iretq' instruction faulted, wo we have the
+                        * 'user' registers saved after the kernel
+                        * %rip:%cs:%fl:%rsp:%ss of the iret, and below that
+                        * the user %rip:%cs:%fl:%rsp:%ss the 'iret' was
+                        * processing.
+                        * We must copy the user register back over the
+                        * kernel fault frame to generate a normal stack
+                        * frame (eg for sending a SIGSEGV).
+                        */
+                       vframe = (void *)((char *)vframe
+                           - offsetof(struct trapframe, tf_rip));
+                       memmove(vframe, frame,
+                           offsetof(struct trapframe, tf_rip));
+                       /* Set the faulting address to the user %eip */
+                       ksi.ksi_addr = (void *)vframe->tf_rip;
+                       break;
+               case 0xac8e:    /* mov 0x98(%rsp),%gs (8e ac 24 98 00 00 00) */
+               case 0xa48e:    /* mov 0xa0(%rsp),%fs (8e a4 24 a0 00 00 00) */
+               case 0x848e:    /* mov 0xa8(%rsp),%es (8e 84 24 a8 00 00 00) */
+               case 0x9c8e:    /* mov 0xb0(%rsp),%ds (8e 9c 24 b0 00 00 00) */
+                       /*
+                        * We faulted loading one if the user segment registers.
+                        * The stack frame containing the user registers is
+                        * still valid and pointed to by tf_rsp.
+                        * Maybe we should check the iretq follows.
+                        */
+                       if (KERNELMODE(vframe->tf_cs, vframe->tf_eflags))
+                               goto we_re_toast;
+                       /* There is no valid address for the fault */
                        break;
-#endif
                default:
                        goto we_re_toast;
                }
-               if (KERNELMODE(vframe->tf_cs, vframe->tf_rflags))
-                       goto we_re_toast;
-
-               frame->tf_rip = (u_int64_t)resume;
-               return;
+               /* XXX: worry about on-stack trampolines for nested
+                * handlers?? */
+               /* Save outer frame for any signal return */
+               l->l_md.md_regs = vframe;
+               (*p->p_emul->e_trapsignal)(l, &ksi);
+               /* Return to user by reloading the user frame */
+               trap_return_fault_return(vframe);
+               /* NOTREACHED */
 
        case T_PROTFLT|T_USER:          /* protection fault */
        case T_TSSFLT|T_USER:
@@ -516,7 +529,7 @@ faultcommon:
                        }
                        printf("uvm_fault(%p, 0x%lx, %d) -> %x\n",
                            map, va, ftype, error);
-                       goto we_re_toast;
+                       goto kernelfault;
                }
                if (error == ENOMEM) {
                        ksi.ksi_signo = SIGKILL;
Index: sys/arch/amd64/amd64/vector.S
===================================================================
RCS file: /cvsroot/src/sys/arch/amd64/amd64/vector.S,v
retrieving revision 1.8
diff -u -p -r1.8 vector.S
--- sys/arch/amd64/amd64/vector.S       11 Dec 2005 12:16:21 -0000      1.8
+++ sys/arch/amd64/amd64/vector.S       12 Jun 2012 22:36:17 -0000
@@ -141,12 +141,37 @@ IDTVEC(trap09)
        ZTRAP(T_FPOPFLT)
 IDTVEC(trap0a)
        TRAP(T_TSSFLT)
-IDTVEC(trap0b)
+IDTVEC(trap0b)                         /* #NP() Segment not present */
        TRAP(T_SEGNPFLT)
+       jmp     check_swapgs
 IDTVEC(trap0c)
        TRAP(T_STKFLT)
+       jmp     check_swapgs
 IDTVEC(trap0d)
        TRAP(T_PROTFLT)
+/* We need to worry about traps before iret after the swapgs.
+ * Might be loading %gs or the iret itself. */
+check_swapgs:
+       INTRENTRY_L(3f,1:)
+2:     sti
+       jmp     calltrap
+3:
+       /* Trap in kernel mode. */
+       /* If faulting instruction is 'iret' or mov to %gs
+        * we may need to do a 'swapgs'. */
+       movq    TF_RIP(%rsp),%rax
+       movq    TF_RSP(%rsp),%rbx       /* Must read %rsp, may be a pad word */
+       cmpl    $0x9824ac8e,(%rax)      /* Fault is mov %gs,0x98(%rsp) ? */
+       jne     4f
+       addw    $7+7,%rax               /* Advance %rip to iret */
+       addq    $TF_TRAPNO+8+8,%rbx     /* %rsp adjust before iret */
+4:     cmpw    $0xcf48,(%rax)          /* Faulting instruction is iretq ? */
+       jne     2b                      /* normal fault in kernel */
+
+       testb   $SEL_UPL,8(%rbx)        /* Check %cs of outer iret frame */
+       je      2b                      /* if iret was to user ... */
+       jmp     1b                      /* ... must restore kernel %gs */
+
 IDTVEC(trap0e)
        TRAP(T_PAGEFLT)
 IDTVEC(intrspurious)
@@ -194,25 +219,20 @@ IDTVEC(exceptions)
        .quad   _C_LABEL(Xtrap1e), _C_LABEL(Xtrap1f)
 
 /*
- * If an error is detected during trap, syscall, or interrupt exit, trap() will
- * change %eip to point to one of these labels.  We clean up the stack, if
- * necessary, and resume as if we were handling a general protection fault.
- * This will cause the process to get a SIGBUS.
- *
- * XXXfvdl currently unused, as pop %ds and pop %es are illegal in long
- * mode. However, if the x86-64 port is going to support USER_LDT, we
- * may need something like this after all.
+ * trap() calls here when it detects a fault in INTRFASTEXIT (loading the
+ * segment registers or during the iret itself).
+ * The address of the (possibly reconstructed) user trap frame is
+ * passed as an argument.
+ * Typically the code will have raised a SIGSEGV which will be actioned
+ * by the code below.
  */
-NENTRY(resume_iret)
-       ZTRAP(T_PROTFLT)
-#if 0
-NENTRY(resume_pop_ds)
-       movl    $GSEL(GDATA_SEL, SEL_KPL),%eax
-       movl    %eax,%es
-NENTRY(resume_pop_es)
-       movl    $T_PROTFLT,TF_TRAPNO(%rsp)
-       jmp     calltrap
-#endif
+_C_LABEL(trap_return_fault_return):    .globl  trap_return_fault_return
+       mov     %rdi,%rsp               /* frame for user return */
+#ifdef DIAGNOSTIC
+       /* We can't recover the saved %rbx, so suppress warning */
+       movl    CPUVAR(ILEVEL),%ebx
+#endif /* DIAGNOSTIC */
+       jmp     2f
 
 /*
  * All traps go through here. Call the generic trap handler, and
Index: sys/arch/amd64/include/frameasm.h
===================================================================
RCS file: /cvsroot/src/sys/arch/amd64/include/frameasm.h,v
retrieving revision 1.1
diff -u -p -r1.1 frameasm.h
--- sys/arch/amd64/include/frameasm.h   26 Apr 2003 18:39:40 -0000      1.1
+++ sys/arch/amd64/include/frameasm.h   12 Jun 2012 22:36:17 -0000
@@ -47,27 +47,32 @@
        movq    TF_RAX(%rsp),%rax       ; \
        addq    $120,%rsp
 
-#define        INTRENTRY \
+#define        INTRENTRY_L(kernel_trap, usertrap) \
        subq    $32,%rsp                ; \
-       testq   $SEL_UPL,56(%rsp)       ; \
-       je      98f                     ; \
+       INTR_SAVE_GPRS                  ; \
+       testb   $SEL_UPL,56(%rsp)       ; \
+       je      kernel_trap             ; \
+usertrap                               ; \
        swapgs                          ; \
        movw    %gs,0(%rsp)             ; \
        movw    %fs,8(%rsp)             ; \
        movw    %es,16(%rsp)            ; \
-       movw    %ds,24(%rsp)            ; \
-98:    INTR_SAVE_GPRS
+       movw    %ds,24(%rsp)
+
+#define        INTRENTRY \
+       INTRENTRY_L(98f,)               ; \
+98:
 
 #define INTRFASTEXIT \
        INTR_RESTORE_GPRS               ; \
        testq   $SEL_UPL,56(%rsp)       ; \
        je      99f                     ; \
        cli                             ; \
-       swapgs                          ; \
-       movw    0(%rsp),%gs             ; \
        movw    8(%rsp),%fs             ; \
        movw    16(%rsp),%es            ; \
        movw    24(%rsp),%ds            ; \
+       swapgs                          ; \
+       movw    0(%rsp),%gs             ; /* can fault */ \
 99:    addq    $48,%rsp                ; \
        iretq
 


Home | Main Index | Thread Index | Old Index