pushl %es
pushl %fs
pushl %gs
- cld
.globl alltraps_with_regs_pushed
alltraps_with_regs_pushed:
mov $KDSEL,%ax
FAKE_MCOUNT(btrap) /* init "from" _btrap -> calltrap */
incl PCPU(cnt)+V_TRAP
/* warning, trap frame dummy arg, no extra reg pushes */
+ cld
pushl %esp /* pass frame by reference */
call trap
addl $4,%esp
* segment register being changed (e.g. by procfs), which is why syscalls
* have to use doreti.
*/
-#define APIC_POP_FRAME POP_FRAME
+#define APIC_POP_FRAME \
+ POP_FRAME ; \
#define IOAPICADDR(irq_num) \
CNAME(ioapic_irqs) + IOAPIC_IRQI_SIZE * (irq_num) + IOAPIC_IRQI_ADDR
/*
* Handle "spurious INTerrupts".
- * Notes:
- * This is different than the "spurious INTerrupt" generated by an
- * 8259 PIC for missing INTs. See the APIC documentation for details.
- * This routine should NOT do an 'EOI' cycle.
+ *
+ * NOTE: This is different than the "spurious INTerrupt" generated by an
+ * 8259 PIC for missing INTs. See the APIC documentation for details.
+ * This routine should NOT do an 'EOI' cycle.
+ *
+ * NOTE: Even though we don't do anything here we must still swapgs if
+ * coming from a user frame in case the iretq faults... just use
+ * the nominal APIC_PUSH_FRAME sequence to get it done.
*/
.text
SUPERALIGN_TEXT
.globl Xspuriousint
Xspuriousint:
-
+ APIC_PUSH_FRAME
/* No EOI cycle used here */
-
+ FAKE_MCOUNT(TF_RIP(%rsp))
+ MEXITCOUNT
+ APIC_POP_FRAME
jmp doreti_iret
#ifdef SMP
.globl calltrap
.type calltrap,@function
calltrap:
+ cld
movq %rsp, %rdi
call trap
MEXITCOUNT
jz 1f
swapgs
1: movq %rsp, %rdi
+ cld
call dblfault_handler
2: hlt
jmp 2b
/* Note: this label is also used by ddb and gdb: */
nmi_calltrap:
FAKE_MCOUNT(TF_RIP(%rsp))
+ cld
movq %rsp, %rdi
call trap
MEXITCOUNT
*/
#define PUSH_DUMMY \
pushfq ; /* phys int frame / flags */ \
- movl %cs,%eax ; \
+ xorq %rax,%rax ; /* something not SEL_UPL */ \
pushq %rax ; /* phys int frame / cs */ \
pushq 3*8(%rsp) ; /* original caller eip */ \
subq $TF_RIP,%rsp ; /* trap frame */ \
msr = ((u_int64_t)GSEL(GCODE_SEL, SEL_KPL) << 32) |
((u_int64_t)GSEL(GUCODE32_SEL, SEL_UPL) << 48);
wrmsr(MSR_STAR, msr);
- wrmsr(MSR_SF_MASK, PSL_NT|PSL_T|PSL_I|PSL_C|PSL_D);
+ wrmsr(MSR_SF_MASK, PSL_NT|PSL_T|PSL_I|PSL_C|PSL_D|PSL_IOPL);
getmemsize(kmdp, physfree);
init_param2(physmem);
msr = ((u_int64_t)GSEL(GCODE_SEL, SEL_KPL) << 32) |
((u_int64_t)GSEL(GUCODE32_SEL, SEL_UPL) << 48);
wrmsr(MSR_STAR, msr);
- wrmsr(MSR_SF_MASK, PSL_NT|PSL_T|PSL_I|PSL_C|PSL_D);
+ wrmsr(MSR_SF_MASK, PSL_NT|PSL_T|PSL_I|PSL_C|PSL_D|PSL_IOPL);
pmap_set_opt(); /* PSE/4MB pages, etc */
#if JGXXX
* PCB_RSP. We push the flags for later restore by cpu_heavy_restore.
*/
pushfq
+ cli
movq $cpu_heavy_restore, %rax
pushq %rax
movq %rsp,TD_SP(%rbx)
* thread but %rsp still points to the old thread's stack, but
* we are protected by a critical section so it is ok.
*/
+ cli
movq %rdi,%rax
movq %rax,PCPU(curthread)
movq TD_SP(%rax),%rsp
movq PCB_R15(%rdx), %r15
movq PCB_RIP(%rdx), %rax
movq %rax, (%rsp)
+ movw $KDSEL,%ax
+ movw %ax,%es
#if JG
/*
pushq %r14
pushq %r15
pushfq
+ cli
#if 1
/*
if (td->td_lwp->lwp_vkernel == NULL) {
if (bootverbose || freeze_on_seg_fault || ddb_on_seg_fault) {
kprintf("seg-fault ft=%04x ff=%04x addr=%p rip=%p "
- "pid=%d p_comm=%s\n",
+ "pid=%d cpu=%d p_comm=%s\n",
ftype, fault_flags,
(void *)frame->tf_addr,
(void *)frame->tf_rip,
- p->p_pid, p->p_comm);
+ p->p_pid, mycpu->gd_cpuid, p->p_comm);
}
#ifdef DDB
while (freeze_on_seg_fault) {
* (which was holding the value of %rcx) is restored for
* the next iteration.
*/
+ if (frame->tf_err != 0 && frame->tf_err != 2)
+ kprintf("lp %s:%d frame->tf_err is weird %ld\n",
+ td->td_comm, lp->lwp_proc->p_pid, frame->tf_err);
frame->tf_rip -= frame->tf_err;
frame->tf_r10 = frame->tf_rcx;
break;
regs->tf_rip = (long)params->func;
regs->tf_rsp = (long)params->stack;
/* Set up argument for function call */
- regs->tf_rdi = (long)params->arg; /* JG Can this be in userspace addresses? */
+ regs->tf_rdi = (long)params->arg;
+
/*
* Set up fake return address. As the lwp function may never return,
* we simply copy out a NULL pointer and force the lwp to receive
return 0;
}
+#if 0
+
+void _test_frame_enter(struct trapframe *frame);
+void _test_frame_exit(struct trapframe *frame);
+
+void
+_test_frame_enter(struct trapframe *frame)
+{
+ thread_t td = curthread;
+
+ if (ISPL(frame->tf_cs) == SEL_UPL) {
+ KKASSERT(td->td_lwp);
+ KASSERT(td->td_lwp->lwp_md.md_regs == frame,
+ ("_test_frame_exit: Frame mismatch %p %p",
+ td->td_lwp->lwp_md.md_regs, frame));
+ td->td_lwp->lwp_saveusp = (void *)frame->tf_rsp;
+ td->td_lwp->lwp_saveupc = (void *)frame->tf_rip;
+ }
+ if ((char *)frame < td->td_kstack ||
+ (char *)frame > td->td_kstack + td->td_kstack_size) {
+ panic("_test_frame_exit: frame not on kstack %p kstack=%p\n",
+ frame, td->td_kstack);
+ }
+}
+
+void
+_test_frame_exit(struct trapframe *frame)
+{
+ thread_t td = curthread;
+
+ if (ISPL(frame->tf_cs) == SEL_UPL) {
+ KKASSERT(td->td_lwp);
+ KASSERT(td->td_lwp->lwp_md.md_regs == frame,
+ ("_test_frame_exit: Frame mismatch %p %p",
+ td->td_lwp->lwp_md.md_regs, frame));
+ if (td->td_lwp->lwp_saveusp != (void *)frame->tf_rsp) {
+ kprintf("_test_frame_exit: %s:%d usp mismatch %p/%p\n",
+ td->td_comm, td->td_proc->p_pid,
+ td->td_lwp->lwp_saveusp,
+ (void *)frame->tf_rsp);
+ }
+ if (td->td_lwp->lwp_saveupc != (void *)frame->tf_rip) {
+ kprintf("_test_frame_exit: %s:%d upc mismatch %p/%p\n",
+ td->td_comm, td->td_proc->p_pid,
+ td->td_lwp->lwp_saveupc,
+ (void *)frame->tf_rip);
+ }
+
+ /*
+ * adulterate the fields to catch entries that
+ * don't run through test_frame_enter
+ */
+ td->td_lwp->lwp_saveusp =
+ (void *)~(intptr_t)td->td_lwp->lwp_saveusp;
+ td->td_lwp->lwp_saveupc =
+ (void *)~(intptr_t)td->td_lwp->lwp_saveupc;
+ }
+ if ((char *)frame < td->td_kstack ||
+ (char *)frame > td->td_kstack + td->td_kstack_size) {
+ panic("_test_frame_exit: frame not on kstack %p kstack=%p\n",
+ frame, td->td_kstack);
+ }
+}
+
+#endif
u_int lwp_kqueue_serial;
struct lwkt_token lwp_token; /* per-lwp token for signal/state */
struct spinlock lwp_spin; /* spinlock for signal handling */
+ void *lwp_reserveds1; /* reserved for lwp_saveusp */
+ void *lwp_reserveds2; /* reserved for lwp_saveupc */
};
struct proc {