From c788f92509ffe89a50613786b2fc2bbf8139a9b6 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Wed, 19 Jun 2013 05:05:16 +0000 Subject: [PATCH] Some clarifications and updates for the comments, mostly retrieved from Bruce Evans. Trim the trailing spaces. MFC after: 1 week --- sys/amd64/amd64/exception.S | 28 +++++++++------- sys/i386/i386/exception.s | 64 ++++++++++++++++++++----------------- 2 files changed, 50 insertions(+), 42 deletions(-) diff --git a/sys/amd64/amd64/exception.S b/sys/amd64/amd64/exception.S index 8fa520206487..a71428153d47 100644 --- a/sys/amd64/amd64/exception.S +++ b/sys/amd64/amd64/exception.S @@ -80,18 +80,22 @@ dtrace_invop_calltrap_addr: * This is equivalent to the i386 port's use of SDT_SYS386TGT. * * The cpu will push a certain amount of state onto the kernel stack for - * the current process. See amd64/include/frame.h. - * This includes the current RFLAGS (status register, which includes + * the current process. See amd64/include/frame.h. + * This includes the current RFLAGS (status register, which includes * the interrupt disable state prior to the trap), the code segment register, - * and the return instruction pointer are pushed by the cpu. The cpu - * will also push an 'error' code for certain traps. We push a dummy - * error code for those traps where the cpu doesn't in order to maintain + * and the return instruction pointer are pushed by the cpu. The cpu + * will also push an 'error' code for certain traps. We push a dummy + * error code for those traps where the cpu doesn't in order to maintain * a consistent frame. We also push a contrived 'trap number'. * - * The cpu does not push the general registers, we must do that, and we - * must restore them prior to calling 'iret'. The cpu adjusts the %cs and - * %ss segment registers, but does not mess with %ds, %es, or %fs. Thus we - * must load them with appropriate values for supervisor mode operation. + * The CPU does not push the general registers, so we must do that, and we + * must restore them prior to calling 'iret'. The CPU adjusts %cs and %ss + * but does not mess with %ds, %es, %gs or %fs. We swap the %gs base for + * for the kernel mode operation shortly, without changes to the selector + * loaded. Since superuser long mode works with any selectors loaded into + * segment registers other then %cs, which makes them mostly unused in long + * mode, and kernel does not reference %fs, leave them alone. The segment + * registers are reloaded on return to the usermode. */ MCOUNT_LABEL(user) @@ -503,7 +507,7 @@ nmi_calltrap: #ifdef HWPMC_HOOKS /* * Capture a userspace callchain if needed. - * + * * - Check if the current trap was from user mode. * - Check if the current thread is valid. * - Check if the thread requires a user call chain to be @@ -549,7 +553,7 @@ outofnmi: * At this point the processor has exited NMI mode and is running * with interrupts turned off on the normal kernel stack. * - * If a pending NMI gets recognized at or after this point, it + * If a pending NMI gets recognized at or after this point, it * will cause a kernel callchain to be traced. * * We turn interrupts back on, and call the user callchain capture hook. @@ -567,7 +571,7 @@ nocallchain: #endif testl %ebx,%ebx jnz doreti_exit -nmi_kernelexit: +nmi_kernelexit: /* * Put back the preserved MSR_GSBASE value. */ diff --git a/sys/i386/i386/exception.s b/sys/i386/i386/exception.s index 6d4c17bc73e6..58cd3e8c6612 100644 --- a/sys/i386/i386/exception.s +++ b/sys/i386/i386/exception.s @@ -54,13 +54,13 @@ .globl dtrace_invop_jump_addr .align 4 .type dtrace_invop_jump_addr, @object - .size dtrace_invop_jump_addr, 4 + .size dtrace_invop_jump_addr, 4 dtrace_invop_jump_addr: .zero 4 .globl dtrace_invop_calltrap_addr .align 4 .type dtrace_invop_calltrap_addr, @object - .size dtrace_invop_calltrap_addr, 4 + .size dtrace_invop_calltrap_addr, 4 dtrace_invop_calltrap_addr: .zero 8 #endif @@ -75,22 +75,22 @@ dtrace_invop_calltrap_addr: * Trap and fault vector routines. * * Most traps are 'trap gates', SDT_SYS386TGT. A trap gate pushes state on - * the stack that mostly looks like an interrupt, but does not disable - * interrupts. A few of the traps we are use are interrupt gates, + * the stack that mostly looks like an interrupt, but does not disable + * interrupts. A few of the traps we are use are interrupt gates, * SDT_SYS386IGT, which are nearly the same thing except interrupts are * disabled on entry. * * The cpu will push a certain amount of state onto the kernel stack for - * the current process. The amount of state depends on the type of trap - * and whether the trap crossed rings or not. See i386/include/frame.h. - * At the very least the current EFLAGS (status register, which includes + * the current process. The amount of state depends on the type of trap + * and whether the trap crossed rings or not. See i386/include/frame.h. + * At the very least the current EFLAGS (status register, which includes * the interrupt disable state prior to the trap), the code segment register, - * and the return instruction pointer are pushed by the cpu. The cpu - * will also push an 'error' code for certain traps. We push a dummy - * error code for those traps where the cpu doesn't in order to maintain + * and the return instruction pointer are pushed by the cpu. The cpu + * will also push an 'error' code for certain traps. We push a dummy + * error code for those traps where the cpu doesn't in order to maintain * a consistent frame. We also push a contrived 'trap number'. * - * The cpu does not push the general registers, we must do that, and we + * The cpu does not push the general registers, we must do that, and we * must restore them prior to calling 'iret'. The cpu adjusts the %cs and * %ss segment registers, but does not mess with %ds, %es, or %fs. Thus we * must load them with appropriate values for supervisor mode operation. @@ -145,13 +145,14 @@ IDTVEC(xmm) pushl $0; TRAP(T_XMMFLT) /* - * alltraps entry point. Interrupts are enabled if this was a trap - * gate (TGT), else disabled if this was an interrupt gate (IGT). - * Note that int0x80_syscall is a trap gate. Interrupt gates are - * used by page faults, non-maskable interrupts, debug and breakpoint + * All traps except ones for syscalls jump to alltraps. If + * interrupts were enabled when the trap occurred, then interrupts + * are enabled now if the trap was through a trap gate, else + * disabled if the trap was through an interrupt gate. Note that + * int0x80_syscall is a trap gate. Interrupt gates are used by + * page faults, non-maskable interrupts, debug and breakpoint * exceptions. */ - SUPERALIGN_TEXT .globl alltraps .type alltraps,@function @@ -168,7 +169,7 @@ calltrap: pushl %esp call trap add $4, %esp - + /* * Return via doreti to handle ASTs. */ @@ -187,10 +188,10 @@ IDTVEC(ill) /* Check if this is a user fault. */ cmpl $GSEL_KPL, 4(%esp) /* Check the code segment. */ - + /* If so, just handle it as a normal trap. */ jne norm_ill - + /* * This is a kernel instruction fault that might have been caused * by a DTrace provider. @@ -215,10 +216,10 @@ norm_ill: #endif /* - * SYSCALL CALL GATE (old entry point for a.out binaries) + * Call gate entry for syscalls (lcall 7,0). + * This is used by FreeBSD 1.x a.out executables and "old" NetBSD executables. * * The intersegment call has been set up to specify one dummy parameter. - * * This leaves a place to put eflags so that the call frame can be * converted to a trap frame. Note that the eflags is (semi-)bogusly * pushed into (what will be) tf_err and then copied later into the @@ -246,11 +247,13 @@ IDTVEC(lcall_syscall) jmp doreti /* - * Call gate entry for FreeBSD ELF and Linux/NetBSD syscall (int 0x80) + * Trap gate entry for syscalls (int 0x80). + * This is used by FreeBSD ELF executables, "new" NetBSD executables, and all + * Linux executables. * - * Even though the name says 'int0x80', this is actually a TGT (trap gate) - * rather then an IGT (interrupt gate). Thus interrupts are enabled on - * entry just as they are for a normal syscall. + * 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 + * a normal syscall. */ SUPERALIGN_TEXT IDTVEC(int0x80_syscall) @@ -348,13 +351,14 @@ doreti_next: /* * PSL_VM must be checked first since segment registers only * have an RPL in non-VM86 mode. + * ASTs can not be handled now if we are in a vm86 call. */ - testl $PSL_VM,TF_EFLAGS(%esp) /* are we in vm86 mode? */ + testl $PSL_VM,TF_EFLAGS(%esp) jz doreti_notvm86 movl PCPU(CURPCB),%ecx - testl $PCB_VM86CALL,PCB_FLAGS(%ecx) /* are we in a vm86 call? */ - jz doreti_ast /* can handle ASTS now if not */ - jmp doreti_exit + testl $PCB_VM86CALL,PCB_FLAGS(%ecx) + jz doreti_ast + jmp doreti_exit doreti_notvm86: testb $SEL_RPL_MASK,TF_CS(%esp) /* are we returning to user mode? */ @@ -401,7 +405,7 @@ doreti_popl_ds: doreti_iret: iret - /* + /* * doreti_iret_fault and friends. Alternative return code for * the case where we get a fault in the doreti_exit code * above. trap() (i386/i386/trap.c) catches this specific