Changeset View
Changeset View
Standalone View
Standalone View
sys/i386/i386/exception.s
Show First 20 Lines • Show All 90 Lines • ▼ Show 20 Lines | |||||
* %ss segment registers, but does not mess with %ds, %es, or %fs. Thus we | * %ss segment registers, but does not mess with %ds, %es, or %fs. Thus we | ||||
* must load them with appropriate values for supervisor mode operation. | * must load them with appropriate values for supervisor mode operation. | ||||
* | * | ||||
* This code is not executed at the linked address, it is copied to the | * This code is not executed at the linked address, it is copied to the | ||||
* trampoline area. As the consequence, all code there and in included files | * trampoline area. As the consequence, all code there and in included files | ||||
* must be PIC. | * must be PIC. | ||||
*/ | */ | ||||
MCOUNT_LABEL(user) | |||||
MCOUNT_LABEL(btrap) | |||||
#define TRAP(a) pushl $(a) ; jmp alltraps | #define TRAP(a) pushl $(a) ; jmp alltraps | ||||
IDTVEC(div) | IDTVEC(div) | ||||
pushl $0; TRAP(T_DIVIDE) | pushl $0; TRAP(T_DIVIDE) | ||||
IDTVEC(bpt) | IDTVEC(bpt) | ||||
pushl $0; TRAP(T_BPTFLT) | pushl $0; TRAP(T_BPTFLT) | ||||
IDTVEC(dtrace_ret) | IDTVEC(dtrace_ret) | ||||
pushl $0; TRAP(T_DTRACE_RET) | pushl $0; TRAP(T_DTRACE_RET) | ||||
▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | IDTVEC(xmm) | ||||
.globl alltraps | .globl alltraps | ||||
.type alltraps,@function | .type alltraps,@function | ||||
alltraps: | alltraps: | ||||
PUSH_FRAME2 | PUSH_FRAME2 | ||||
alltraps_with_regs_pushed: | alltraps_with_regs_pushed: | ||||
SET_KERNEL_SREGS | SET_KERNEL_SREGS | ||||
cld | cld | ||||
KENTER | KENTER | ||||
FAKE_MCOUNT(TF_EIP(%esp)) | |||||
calltrap: | calltrap: | ||||
pushl %esp | pushl %esp | ||||
movl $trap,%eax | movl $trap,%eax | ||||
call *%eax | call *%eax | ||||
add $4, %esp | add $4, %esp | ||||
/* | /* | ||||
* Return via doreti to handle ASTs. | * Return via doreti to handle ASTs. | ||||
*/ | */ | ||||
MEXITCOUNT | |||||
jmp doreti | jmp doreti | ||||
.globl irettraps | .globl irettraps | ||||
.type irettraps,@function | .type irettraps,@function | ||||
irettraps: | irettraps: | ||||
testl $PSL_VM, TF_EFLAGS-TF_TRAPNO(%esp) | testl $PSL_VM, TF_EFLAGS-TF_TRAPNO(%esp) | ||||
jnz alltraps | jnz alltraps | ||||
testb $SEL_RPL_MASK, TF_CS-TF_TRAPNO(%esp) | testb $SEL_RPL_MASK, TF_CS-TF_TRAPNO(%esp) | ||||
Show All 28 Lines | 3: leal (doreti_popl_es - 1b)(%ebx), %edx | ||||
movl $(2 * TF_SZ - TF_ES), %ecx | movl $(2 * TF_SZ - TF_ES), %ecx | ||||
jmp 6f | jmp 6f | ||||
4: leal (doreti_popl_fs - 1b)(%ebx), %edx | 4: leal (doreti_popl_fs - 1b)(%ebx), %edx | ||||
cmpl %edx, TF_EIP(%esp) | cmpl %edx, TF_EIP(%esp) | ||||
jne 5f | jne 5f | ||||
movl $(2 * TF_SZ - TF_FS), %ecx | movl $(2 * TF_SZ - TF_FS), %ecx | ||||
jmp 6f | jmp 6f | ||||
/* kernel mode, normal */ | /* kernel mode, normal */ | ||||
5: FAKE_MCOUNT(TF_EIP(%esp)) | 5: jmp calltrap | ||||
jmp calltrap | |||||
6: cmpl $PMAP_TRM_MIN_ADDRESS, %esp /* trampoline stack ? */ | 6: cmpl $PMAP_TRM_MIN_ADDRESS, %esp /* trampoline stack ? */ | ||||
jb 5b /* if not, no need to change stacks */ | jb 5b /* if not, no need to change stacks */ | ||||
movl (tramp_idleptd - 1b)(%ebx), %eax | movl (tramp_idleptd - 1b)(%ebx), %eax | ||||
movl %eax, %cr3 | movl %eax, %cr3 | ||||
movl PCPU(KESP0), %edx | movl PCPU(KESP0), %edx | ||||
subl %ecx, %edx | subl %ecx, %edx | ||||
movl %edx, %edi | movl %edx, %edi | ||||
movl %esp, %esi | movl %esp, %esi | ||||
rep; movsb | rep; movsb | ||||
movl %edx, %esp | movl %edx, %esp | ||||
FAKE_MCOUNT(TF_EIP(%esp)) | |||||
jmp calltrap | jmp calltrap | ||||
/* | /* | ||||
* Privileged instruction fault. | * Privileged instruction fault. | ||||
*/ | */ | ||||
#ifdef KDTRACE_HOOKS | #ifdef KDTRACE_HOOKS | ||||
SUPERALIGN_TEXT | SUPERALIGN_TEXT | ||||
IDTVEC(ill) | IDTVEC(ill) | ||||
▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | IDTVEC(dbg) | ||||
SET_KERNEL_SREGS | SET_KERNEL_SREGS | ||||
cld | cld | ||||
movl %cr3, %eax | movl %cr3, %eax | ||||
movl %eax, TF_ERR(%esp) | movl %eax, TF_ERR(%esp) | ||||
call 1f | call 1f | ||||
1: popl %eax | 1: popl %eax | ||||
movl (tramp_idleptd - 1b)(%eax), %eax | movl (tramp_idleptd - 1b)(%eax), %eax | ||||
movl %eax, %cr3 | movl %eax, %cr3 | ||||
FAKE_MCOUNT(TF_EIP(%esp)) | |||||
testl $PSL_VM, TF_EFLAGS(%esp) | testl $PSL_VM, TF_EFLAGS(%esp) | ||||
jnz dbg_user | jnz dbg_user | ||||
testb $SEL_RPL_MASK,TF_CS(%esp) | testb $SEL_RPL_MASK,TF_CS(%esp) | ||||
jz calltrap | jz calltrap | ||||
dbg_user: | dbg_user: | ||||
NMOVE_STACKS | NMOVE_STACKS | ||||
movl $handle_ibrs_entry,%eax | movl $handle_ibrs_entry,%eax | ||||
call *%eax | call *%eax | ||||
pushl %esp | pushl %esp | ||||
movl $trap,%eax | movl $trap,%eax | ||||
call *%eax | call *%eax | ||||
add $4, %esp | add $4, %esp | ||||
movl $T_RESERVED, TF_TRAPNO(%esp) | movl $T_RESERVED, TF_TRAPNO(%esp) | ||||
MEXITCOUNT | |||||
jmp doreti | jmp doreti | ||||
IDTVEC(mchk) | IDTVEC(mchk) | ||||
pushl $0 | pushl $0 | ||||
pushl $T_MCHK | pushl $T_MCHK | ||||
jmp nmi_mchk_common | jmp nmi_mchk_common | ||||
IDTVEC(nmi) | IDTVEC(nmi) | ||||
Show All 14 Lines | nmi_mchk_common: | ||||
* previous state if we come from the kernel. | * previous state if we come from the kernel. | ||||
*/ | */ | ||||
movl %cr3, %eax | movl %cr3, %eax | ||||
movl %eax, TF_ERR(%esp) | movl %eax, TF_ERR(%esp) | ||||
call 1f | call 1f | ||||
1: popl %eax | 1: popl %eax | ||||
movl (tramp_idleptd - 1b)(%eax), %eax | movl (tramp_idleptd - 1b)(%eax), %eax | ||||
movl %eax, %cr3 | movl %eax, %cr3 | ||||
FAKE_MCOUNT(TF_EIP(%esp)) | |||||
jmp calltrap | jmp calltrap | ||||
/* | /* | ||||
* Trap gate entry for syscalls (int 0x80). | * Trap gate entry for syscalls (int 0x80). | ||||
* This is used by FreeBSD ELF executables, "new" a.out executables, and all | * This is used by FreeBSD ELF executables, "new" a.out executables, and all | ||||
* Linux executables. | * Linux executables. | ||||
* | * | ||||
* Even though the name says 'int0x80', this is actually a trap gate, not an | * Even though the name says 'int0x80', this is actually a trap gate, not an | ||||
* interrupt gate. Thus interrupts are enabled on entry just as they are for | * interrupt gate. Thus interrupts are enabled on entry just as they are for | ||||
* a normal syscall. | * a normal syscall. | ||||
*/ | */ | ||||
SUPERALIGN_TEXT | SUPERALIGN_TEXT | ||||
IDTVEC(int0x80_syscall) | IDTVEC(int0x80_syscall) | ||||
pushl $2 /* sizeof "int 0x80" */ | pushl $2 /* sizeof "int 0x80" */ | ||||
pushl $0 /* tf_trapno */ | pushl $0 /* tf_trapno */ | ||||
PUSH_FRAME2 | PUSH_FRAME2 | ||||
SET_KERNEL_SREGS | SET_KERNEL_SREGS | ||||
cld | cld | ||||
MOVE_STACKS | MOVE_STACKS | ||||
movl $handle_ibrs_entry,%eax | movl $handle_ibrs_entry,%eax | ||||
call *%eax | call *%eax | ||||
sti | sti | ||||
FAKE_MCOUNT(TF_EIP(%esp)) | |||||
pushl %esp | pushl %esp | ||||
movl $syscall, %eax | movl $syscall, %eax | ||||
call *%eax | call *%eax | ||||
add $4, %esp | add $4, %esp | ||||
MEXITCOUNT | |||||
jmp doreti | jmp doreti | ||||
ENTRY(fork_trampoline) | ENTRY(fork_trampoline) | ||||
pushl %esp /* trapframe pointer */ | pushl %esp /* trapframe pointer */ | ||||
pushl %ebx /* arg1 */ | pushl %ebx /* arg1 */ | ||||
pushl %esi /* function */ | pushl %esi /* function */ | ||||
movl $fork_exit, %eax | movl $fork_exit, %eax | ||||
call *%eax | call *%eax | ||||
addl $12,%esp | addl $12,%esp | ||||
/* cut from syscall */ | /* cut from syscall */ | ||||
/* | /* | ||||
* Return via doreti to handle ASTs. | * Return via doreti to handle ASTs. | ||||
*/ | */ | ||||
MEXITCOUNT | |||||
jmp doreti | jmp doreti | ||||
/* | |||||
* To efficiently implement classification of trap and interrupt handlers | |||||
* for profiling, there must be only trap handlers between the labels btrap | |||||
* and bintr, and only interrupt handlers between the labels bintr and | |||||
* eintr. This is implemented (partly) by including files that contain | |||||
* some of the handlers. Before including the files, set up a normal asm | |||||
* environment so that the included files doen't need to know that they are | |||||
* included. | |||||
*/ | |||||
.data | .data | ||||
.p2align 4 | .p2align 4 | ||||
.text | .text | ||||
SUPERALIGN_TEXT | SUPERALIGN_TEXT | ||||
MCOUNT_LABEL(bintr) | |||||
#ifdef DEV_ATPIC | #ifdef DEV_ATPIC | ||||
#include <i386/i386/atpic_vector.s> | #include <i386/i386/atpic_vector.s> | ||||
#endif | #endif | ||||
#if defined(DEV_APIC) && defined(DEV_ATPIC) | #if defined(DEV_APIC) && defined(DEV_ATPIC) | ||||
.data | .data | ||||
.p2align 4 | .p2align 4 | ||||
.text | .text | ||||
SUPERALIGN_TEXT | SUPERALIGN_TEXT | ||||
#endif | #endif | ||||
#ifdef DEV_APIC | #ifdef DEV_APIC | ||||
#include <i386/i386/apic_vector.s> | #include <i386/i386/apic_vector.s> | ||||
#endif | #endif | ||||
.data | .data | ||||
.p2align 4 | .p2align 4 | ||||
.text | .text | ||||
SUPERALIGN_TEXT | SUPERALIGN_TEXT | ||||
#include <i386/i386/vm86bios.s> | #include <i386/i386/vm86bios.s> | ||||
.text | .text | ||||
MCOUNT_LABEL(eintr) | |||||
#include <i386/i386/copyout_fast.s> | #include <i386/i386/copyout_fast.s> | ||||
/* | /* | ||||
* void doreti(struct trapframe) | * void doreti(struct trapframe) | ||||
* | * | ||||
* Handle return from interrupts, traps and syscalls. | * Handle return from interrupts, traps and syscalls. | ||||
*/ | */ | ||||
.text | .text | ||||
SUPERALIGN_TEXT | SUPERALIGN_TEXT | ||||
.type doreti,@function | .type doreti,@function | ||||
.globl doreti | .globl doreti | ||||
doreti: | doreti: | ||||
FAKE_MCOUNT($bintr) /* init "from" bintr -> doreti */ | |||||
doreti_next: | doreti_next: | ||||
/* | /* | ||||
* Check if ASTs can be handled now. ASTs cannot be safely | * Check if ASTs can be handled now. ASTs cannot be safely | ||||
* processed when returning from an NMI. | * processed when returning from an NMI. | ||||
*/ | */ | ||||
cmpb $T_NMI,TF_TRAPNO(%esp) | cmpb $T_NMI,TF_TRAPNO(%esp) | ||||
#ifdef HWPMC_HOOKS | #ifdef HWPMC_HOOKS | ||||
je doreti_nmi | je doreti_nmi | ||||
Show All 36 Lines | doreti_ast: | ||||
/* | /* | ||||
* doreti_exit: pop registers, iret. | * doreti_exit: pop registers, iret. | ||||
* | * | ||||
* The segment register pop is a special case, since it may | * The segment register pop is a special case, since it may | ||||
* fault if (for example) a sigreturn specifies bad segment | * fault if (for example) a sigreturn specifies bad segment | ||||
* registers. The fault is handled in trap.c. | * registers. The fault is handled in trap.c. | ||||
*/ | */ | ||||
doreti_exit: | doreti_exit: | ||||
MEXITCOUNT | |||||
cmpl $T_NMI, TF_TRAPNO(%esp) | cmpl $T_NMI, TF_TRAPNO(%esp) | ||||
je doreti_iret_nmi | je doreti_iret_nmi | ||||
cmpl $T_MCHK, TF_TRAPNO(%esp) | cmpl $T_MCHK, TF_TRAPNO(%esp) | ||||
je doreti_iret_nmi | je doreti_iret_nmi | ||||
cmpl $T_TRCTRAP, TF_TRAPNO(%esp) | cmpl $T_TRCTRAP, TF_TRAPNO(%esp) | ||||
je doreti_iret_nmi | je doreti_iret_nmi | ||||
movl $TF_SZ, %ecx | movl $TF_SZ, %ecx | ||||
testl $PSL_VM,TF_EFLAGS(%esp) | testl $PSL_VM,TF_EFLAGS(%esp) | ||||
▲ Show 20 Lines • Show All 145 Lines • Show Last 20 Lines |