1 /* $NetBSD: frameasm.h,v 1.10 2007/11/29 09:53:33 yamt Exp $ */ 2 3 #ifndef _I386_FRAMEASM_H_ 4 #define _I386_FRAMEASM_H_ 5 6 #ifdef _KERNEL_OPT 7 #include "opt_multiprocessor.h" 8 #endif 9 10 #ifndef TRAPLOG 11 #define TLOG /**/ 12 #else 13 /* 14 * Fill in trap record 15 */ 16 #define TLOG \ 17 9: \ 18 movl %fs:CPU_TLOG_OFFSET, %eax; \ 19 movl %fs:CPU_TLOG_BASE, %ebx; \ 20 addl $SIZEOF_TREC,%eax; \ 21 andl $SIZEOF_TLOG-1,%eax; \ 22 addl %eax,%ebx; \ 23 movl %eax,%fs:CPU_TLOG_OFFSET; \ 24 movl %esp,TREC_SP(%ebx); \ 25 movl $9b,TREC_HPC(%ebx); \ 26 movl TF_EIP(%esp),%eax; \ 27 movl %eax,TREC_IPC(%ebx); \ 28 rdtsc ; \ 29 movl %eax,TREC_TSC(%ebx); \ 30 movl $MSR_LASTBRANCHFROMIP,%ecx; \ 31 rdmsr ; \ 32 movl %eax,TREC_LBF(%ebx); \ 33 incl %ecx ; \ 34 rdmsr ; \ 35 movl %eax,TREC_LBT(%ebx); \ 36 incl %ecx ; \ 37 rdmsr ; \ 38 movl %eax,TREC_IBF(%ebx); \ 39 incl %ecx ; \ 40 rdmsr ; \ 41 movl %eax,TREC_IBT(%ebx) 42 #endif 43 44 /* 45 * These are used on interrupt or trap entry or exit. 46 */ 47 #define INTRENTRY \ 48 subl $TF_PUSHSIZE,%esp ; \ 49 movl %gs,TF_GS(%esp) ; \ 50 movl %fs,TF_FS(%esp) ; \ 51 movl %eax,TF_EAX(%esp) ; \ 52 movl %es,TF_ES(%esp) ; \ 53 movl %ds,TF_DS(%esp) ; \ 54 movl $GSEL(GDATA_SEL, SEL_KPL),%eax ; \ 55 movl %edi,TF_EDI(%esp) ; \ 56 movl %esi,TF_ESI(%esp) ; \ 57 movl %eax,%ds ; \ 58 movl %ebp,TF_EBP(%esp) ; \ 59 movl %eax,%es ; \ 60 movl %ebx,TF_EBX(%esp) ; \ 61 movl %eax,%gs ; \ 62 movl %edx,TF_EDX(%esp) ; \ 63 movl $GSEL(GCPU_SEL, SEL_KPL),%eax ; \ 64 movl %ecx,TF_ECX(%esp) ; \ 65 movl %eax,%fs ; \ 66 cld ; \ 67 TLOG 68 69 /* 70 * INTRFASTEXIT should be in sync with trap(), resume_iret and friends. 71 */ 72 #define INTRFASTEXIT \ 73 movl TF_GS(%esp),%gs ; \ 74 movl TF_FS(%esp),%fs ; \ 75 movl TF_ES(%esp),%es ; \ 76 movl TF_DS(%esp),%ds ; \ 77 movl TF_EDI(%esp),%edi ; \ 78 movl TF_ESI(%esp),%esi ; \ 79 movl TF_EBP(%esp),%ebp ; \ 80 movl TF_EBX(%esp),%ebx ; \ 81 movl TF_EDX(%esp),%edx ; \ 82 movl TF_ECX(%esp),%ecx ; \ 83 movl TF_EAX(%esp),%eax ; \ 84 addl $(TF_PUSHSIZE+8),%esp ; \ 85 iret 86 87 #define DO_DEFERRED_SWITCH \ 88 cmpl $0, CPUVAR(WANT_PMAPLOAD) ; \ 89 jz 1f ; \ 90 call _C_LABEL(pmap_load) ; \ 91 1: 92 93 #define DO_DEFERRED_SWITCH_RETRY \ 94 1: ; \ 95 cmpl $0, CPUVAR(WANT_PMAPLOAD) ; \ 96 jz 1f ; \ 97 call _C_LABEL(pmap_load) ; \ 98 jmp 1b ; \ 99 1: 100 101 #define CHECK_DEFERRED_SWITCH \ 102 cmpl $0, CPUVAR(WANT_PMAPLOAD) 103 104 #define CHECK_ASTPENDING(reg) movl CPUVAR(CURLWP),reg ; \ 105 cmpl $0, reg ; \ 106 je 1f ; \ 107 cmpl $0, L_MD_ASTPENDING(reg); \ 108 1: 109 #define CLEAR_ASTPENDING(reg) movl $0, L_MD_ASTPENDING(reg) 110 111 /* 112 * IDEPTH_INCR: 113 * increase ci_idepth and switch to the interrupt stack if necessary. 114 * note that the initial value of ci_idepth is -1. 115 * 116 * => should be called with interrupt disabled. 117 * => save the old value of %esp in %eax. 118 */ 119 120 #define IDEPTH_INCR \ 121 incl CPUVAR(IDEPTH); \ 122 movl %esp, %eax; \ 123 jne 999f; \ 124 movl CPUVAR(INTRSTACK), %esp; \ 125 999: pushl %eax; \ 126 127 /* 128 * IDEPTH_DECR: 129 * decrement ci_idepth and switch back to 130 * the original stack saved by IDEPTH_INCR. 131 * 132 * => should be called with interrupt disabled. 133 */ 134 135 #define IDEPTH_DECR \ 136 popl %esp; \ 137 decl CPUVAR(IDEPTH) 138 139 #endif /* _I386_FRAMEASM_H_ */ 140