version 1.24.14.2, 2014/08/20 00:02:42 |
version 1.24.14.3, 2017/12/03 11:35:47 |
|
|
* %r13 address to return to |
* %r13 address to return to |
*/ |
*/ |
IDTVEC(softintr) |
IDTVEC(softintr) |
pushq $_C_LABEL(softintr_ret) /* set up struct switchframe */ |
/* set up struct switchframe */ |
|
pushq $_C_LABEL(softintr_ret) |
pushq %rbx |
pushq %rbx |
pushq %r12 |
pushq %r12 |
pushq %r13 |
pushq %r13 |
pushq %r14 |
pushq %r14 |
pushq %r15 |
pushq %r15 |
|
|
movl $IPL_HIGH,CPUVAR(ILEVEL) |
movl $IPL_HIGH,CPUVAR(ILEVEL) |
movq CPUVAR(CURLWP),%r15 |
movq CPUVAR(CURLWP),%r15 |
movq IS_LWP(%rax),%rdi /* switch to handler LWP */ |
movq IS_LWP(%rax),%rdi /* switch to handler LWP */ |
movq L_PCB(%rdi),%rdx |
movq L_PCB(%rdi),%rdx |
movq L_PCB(%r15),%rcx |
movq L_PCB(%r15),%rcx |
movq %rdi,CPUVAR(CURLWP) |
movq %rdi,CPUVAR(CURLWP) |
|
|
|
/* save old context */ |
movq %rsp,PCB_RSP(%rcx) |
movq %rsp,PCB_RSP(%rcx) |
movq %rbp,PCB_RBP(%rcx) |
movq %rbp,PCB_RBP(%rcx) |
movq PCB_RSP0(%rdx),%rsp /* onto new stack */ |
|
|
/* switch to the new stack */ |
|
movq PCB_RSP0(%rdx),%rsp |
|
|
|
/* dispatch */ |
sti |
sti |
movq %r15,%rdi /* interrupted LWP */ |
movq %r15,%rdi /* interrupted LWP */ |
movl IS_MAXLEVEL(%rax),%esi /* ipl to run at */ |
movl IS_MAXLEVEL(%rax),%esi /* ipl to run at */ |
call _C_LABEL(softint_dispatch)/* run handlers */ |
call _C_LABEL(softint_dispatch)/* run handlers */ |
cli |
cli |
|
|
|
/* restore old context */ |
movq L_PCB(%r15),%rcx |
movq L_PCB(%r15),%rcx |
movq PCB_RSP(%rcx),%rsp |
movq PCB_RSP(%rcx),%rsp |
|
|
xchgq %r15,CPUVAR(CURLWP) /* must be globally visible */ |
xchgq %r15,CPUVAR(CURLWP) /* must be globally visible */ |
popq %r15 /* unwind switchframe */ |
popq %r15 /* unwind switchframe */ |
addq $(5 * 8),%rsp |
addq $(5 * 8),%rsp |
jmp *%r13 /* back to splx/doreti */ |
jmp *%r13 /* back to Xspllower/Xdoreti */ |
END(Xsoftintr) |
END(Xsoftintr) |
|
|
/* |
/* |
|
|
*/ |
*/ |
NENTRY(softintr_ret) |
NENTRY(softintr_ret) |
incl CPUVAR(MTX_COUNT) /* re-adjust after mi_switch */ |
incl CPUVAR(MTX_COUNT) /* re-adjust after mi_switch */ |
movl $0, L_CTXSWTCH(%rax) /* %rax from cpu_switchto */ |
movl $0,L_CTXSWTCH(%rax) /* %rax from cpu_switchto */ |
cli |
cli |
jmp *%r13 /* back to splx/doreti */ |
jmp *%r13 /* back to Xspllower/Xdoreti */ |
END(softintr_ret) |
END(softintr_ret) |
|
|
/* |
/* |
Line 150 END(softint_trigger) |
|
Line 161 END(softint_trigger) |
|
* Handles preemption interrupts via Xspllower(). |
* Handles preemption interrupts via Xspllower(). |
*/ |
*/ |
IDTVEC(preemptrecurse) |
IDTVEC(preemptrecurse) |
movl $IPL_PREEMPT, CPUVAR(ILEVEL) |
movl $IPL_PREEMPT,CPUVAR(ILEVEL) |
sti |
sti |
xorq %rdi, %rdi |
xorq %rdi,%rdi |
call _C_LABEL(kpreempt) |
call _C_LABEL(kpreempt) |
cli |
cli |
jmp *%r13 |
jmp *%r13 /* back to Xspllower */ |
END(Xpreemptrecurse) |
END(Xpreemptrecurse) |
|
|
/* |
/* |
Line 164 END(Xpreemptrecurse) |
|
Line 175 END(Xpreemptrecurse) |
|
* Handles preemption interrupts via Xdoreti(). |
* Handles preemption interrupts via Xdoreti(). |
*/ |
*/ |
IDTVEC(preemptresume) |
IDTVEC(preemptresume) |
movl $IPL_PREEMPT, CPUVAR(ILEVEL) |
movl $IPL_PREEMPT,CPUVAR(ILEVEL) |
sti |
sti |
testq $SEL_RPL, TF_CS(%rsp) |
testq $SEL_RPL,TF_CS(%rsp) |
jnz 1f |
jnz 1f |
movq TF_RIP(%rsp), %rdi |
movq TF_RIP(%rsp),%rdi |
call _C_LABEL(kpreempt) # from kernel |
call _C_LABEL(kpreempt) /* from kernel */ |
cli |
cli |
jmp *%r13 |
jmp *%r13 /* back to Xdoreti */ |
1: |
1: |
call _C_LABEL(preempt) # from user |
call _C_LABEL(preempt) /* from user */ |
cli |
cli |
jmp *%r13 |
jmp *%r13 /* back to Xdoreti */ |
END(Xpreemptresume) |
END(Xpreemptresume) |
|
|
/* |
/* |
|
|
* are disabled via eflags/IE. |
* are disabled via eflags/IE. |
*/ |
*/ |
ENTRY(spllower) |
ENTRY(spllower) |
cmpl CPUVAR(ILEVEL), %edi |
cmpl CPUVAR(ILEVEL),%edi |
jae 1f |
jae 1f |
movl CPUVAR(IUNMASK)(,%rdi,4), %edx |
movl CPUVAR(IUNMASK)(,%rdi,4),%edx |
pushf |
pushf |
cli |
cli |
testl CPUVAR(IPENDING), %edx |
testl CPUVAR(IPENDING),%edx |
jnz 2f |
jnz 2f |
movl %edi, CPUVAR(ILEVEL) |
movl %edi,CPUVAR(ILEVEL) |
popf |
popf |
1: |
1: |
ret |
ret |
Line 224 LABEL(spllower_end) |
|
Line 235 LABEL(spllower_end) |
|
* |
* |
* For cmpxchg8b, edx/ecx are the high words and eax/ebx the low. |
* For cmpxchg8b, edx/ecx are the high words and eax/ebx the low. |
* |
* |
* edx : eax = old level / old ipending |
* edx : eax = old level / old ipending |
* ecx : ebx = new level / old ipending |
* ecx : ebx = new level / old ipending |
*/ |
*/ |
ENTRY(cx8_spllower) |
ENTRY(cx8_spllower) |
Line 260 LABEL(cx8_spllower_end) |
|
Line 271 LABEL(cx8_spllower_end) |
|
|
|
/* |
/* |
* void Xspllower(int s); |
* void Xspllower(int s); |
* |
* |
* Process pending interrupts. |
* Process pending interrupts. |
* |
* |
* Important registers: |
* Important registers: |
Line 283 IDTVEC(spllower) |
|
Line 294 IDTVEC(spllower) |
|
pushq %r13 |
pushq %r13 |
pushq %r12 |
pushq %r12 |
movl %edi,%ebx |
movl %edi,%ebx |
leaq 1f(%rip),%r13 # address to resume loop at |
leaq 1f(%rip),%r13 /* address to resume loop at */ |
1: movl %ebx,%eax # get cpl |
1: movl %ebx,%eax /* get cpl */ |
movl CPUVAR(IUNMASK)(,%rax,4),%eax |
movl CPUVAR(IUNMASK)(,%rax,4),%eax |
CLI(si) |
CLI(si) |
andl CPUVAR(IPENDING),%eax # any non-masked bits left? |
andl CPUVAR(IPENDING),%eax /* any non-masked bits left? */ |
jz 2f |
jz 2f |
bsrl %eax,%eax |
bsrl %eax,%eax |
btrl %eax,CPUVAR(IPENDING) |
btrl %eax,CPUVAR(IPENDING) |
Line 303 IDTVEC(spllower) |
|
Line 314 IDTVEC(spllower) |
|
END(Xspllower) |
END(Xspllower) |
|
|
/* |
/* |
|
* void Xdoreti(void); |
|
* |
* Handle return from interrupt after device handler finishes. |
* Handle return from interrupt after device handler finishes. |
* |
* |
* Important registers: |
* Important registers: |
|
|
* r13 - address to resume loop at |
* r13 - address to resume loop at |
*/ |
*/ |
IDTVEC(doreti) |
IDTVEC(doreti) |
popq %rbx # get previous priority |
popq %rbx /* get previous priority */ |
decl CPUVAR(IDEPTH) |
decl CPUVAR(IDEPTH) |
leaq 1f(%rip),%r13 |
leaq 1f(%rip),%r13 |
1: movl %ebx,%eax |
1: movl %ebx,%eax |
|
|
CLI(si) |
CLI(si) |
andl CPUVAR(IPENDING),%eax |
andl CPUVAR(IPENDING),%eax |
jz 2f |
jz 2f |
bsrl %eax,%eax # slow, but not worth optimizing |
bsrl %eax,%eax /* slow, but not worth optimizing */ |
btrl %eax,CPUVAR(IPENDING) |
btrl %eax,CPUVAR(IPENDING) |
movq CPUVAR(ISOURCES)(,%rax, 8),%rax |
movq CPUVAR(ISOURCES)(,%rax,8),%rax |
jmp *IS_RESUME(%rax) |
jmp *IS_RESUME(%rax) |
2: /* Check for ASTs on exit to user mode. */ |
2: /* Check for ASTs on exit to user mode. */ |
movl %ebx,CPUVAR(ILEVEL) |
movl %ebx,CPUVAR(ILEVEL) |
5: |
5: |
testb $SEL_RPL,TF_CS(%rsp) |
testb $SEL_RPL,TF_CS(%rsp) |
jz 6f |
jz 6f |
|
|
.type _C_LABEL(doreti_checkast), @function |
.type _C_LABEL(doreti_checkast), @function |