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