/kernel/trunk/tools/amd64/gencontext.c |
---|
37,28 → 37,6 |
fprintf(f,"#define OFFSET_R15 0x%x\n", ((int) &pctx->r15) - (int) pctx); |
fprintf(f,"#define OFFSET_IPL 0x%x\n", ((int) &pctx->ipl) - (int) pctx); |
fprintf(f, "\n"); |
#define ifpr(big, nm) fprintf(f, "#define IOFFSET_" #big " 0x%x\n", ((int) &ipctx->nm) - (int) ipctx) |
ifpr(RAX, rax); |
ifpr(RBX, rbx); |
ifpr(RCX, rcx); |
ifpr(RDX, rdx); |
ifpr(RSI, rsi); |
ifpr(RDI, rdi); |
ifpr(R8, r8); |
ifpr(R9, r9); |
ifpr(R10, r10); |
ifpr(R11, r11); |
ifpr(R12, r12); |
ifpr(R13, r13); |
ifpr(R14, r14); |
ifpr(R15, r15); |
ifpr(RBP, rbp); |
fprintf(f, "#define IREGISTER_SPACE %d\n", sizeof(ictx)); |
fclose(f); |
return 0; |
/kernel/trunk/arch/amd64/include/context_offset.h |
---|
8,20 → 8,3 |
#define OFFSET_R14 0x30 |
#define OFFSET_R15 0x38 |
#define OFFSET_IPL 0x40 |
#define IOFFSET_RAX 0x0 |
#define IOFFSET_RBX 0x8 |
#define IOFFSET_RCX 0x10 |
#define IOFFSET_RDX 0x18 |
#define IOFFSET_RSI 0x20 |
#define IOFFSET_RDI 0x28 |
#define IOFFSET_R8 0x30 |
#define IOFFSET_R9 0x38 |
#define IOFFSET_R10 0x40 |
#define IOFFSET_R11 0x48 |
#define IOFFSET_R12 0x50 |
#define IOFFSET_R13 0x58 |
#define IOFFSET_R14 0x60 |
#define IOFFSET_R15 0x68 |
#define IOFFSET_RBP 0x70 |
#define IREGISTER_SPACE 120 |
/kernel/trunk/arch/amd64/include/interrupt.h |
---|
76,10 → 76,13 |
__u64 r13; |
__u64 r14; |
__u64 r15; |
/* These 2 items MUST be last parts of the structure */ |
__u64 rbp; |
__u64 stack[0]; /* Additional data on stack */ |
} __attribute__ ((packed)); |
__u64 error_word; |
__u64 rip; |
__u64 cs; |
__u64 rflags; |
__u64 stack[]; /* Additional data on stack */ |
}; |
extern void (* disable_irqs_function)(__u16 irqmask); |
extern void (* enable_irqs_function)(__u16 irqmask); |
/kernel/trunk/arch/amd64/src/asm_utils.S |
---|
26,15 → 26,29 |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
#define IREGISTER_SPACE 120 |
#define IOFFSET_RAX 0x0 |
#define IOFFSET_RBX 0x8 |
#define IOFFSET_RCX 0x10 |
#define IOFFSET_RDX 0x18 |
#define IOFFSET_RSI 0x20 |
#define IOFFSET_RDI 0x28 |
#define IOFFSET_R8 0x30 |
#define IOFFSET_R9 0x38 |
#define IOFFSET_R10 0x40 |
#define IOFFSET_R11 0x48 |
#define IOFFSET_R12 0x50 |
#define IOFFSET_R13 0x58 |
#define IOFFSET_R14 0x60 |
#define IOFFSET_R15 0x68 |
#define IOFFSET_RBP 0x70 |
# Mask for interrupts 0 - 31 (bits 0 - 31) where 0 means that int has no error word |
# and 1 means interrupt with error word |
#define ERROR_WORD_INTERRUPT_LIST 0x00027D00 |
#include <arch/pm.h> |
#include <arch/context_offset.h> |
#include <arch/mm/page.h> |
.text |
147,40 → 161,52 |
# Declare interrupt handlers for n interrupt |
# vectors starting at vector i. |
# |
# The handlers setup data segment registers |
# and call exc_dispatch(). |
# The handlers call exc_dispatch(). |
# |
.macro handler i n |
/* |
* Choose between version with error code and version without error code. |
* Both versions have to be of the same size. amd64 assembly is, however, |
* a little bit tricky. For instance, subq $0x80, %rsp and subq $0x78, %rsp |
* can result in two instructions with different op-code lengths. |
* Therefore, pay special attention to the extra NOP's that serve as |
* a necessary fill. |
*/ |
.iflt \i-32 |
.if (1 << \i) & ERROR_WORD_INTERRUPT_LIST |
/* |
* Version with error word. |
*/ |
subq $IREGISTER_SPACE, %rsp |
nop |
nop |
nop |
.else |
/* |
* Version without error word, |
*/ |
subq $(IREGISTER_SPACE+8), %rsp |
.endif |
.else |
/* |
* Version without error word, |
*/ |
subq $(IREGISTER_SPACE+8), %rsp |
.endif |
save_all_gpr |
movq $(\i),%rdi # %rdi - first parameter |
movq %rsp, %rsi # %rsi - pointer to interrupt_context |
call exc_dispatch # exc_dispatch(i, stack) |
movq %rsp, %rsi # %rsi - pointer to istate |
call exc_dispatch # exc_dispatch(i, istate) |
# Test if this is interrupt with error word or not |
mov $\i,%cl; |
movl $1,%eax; |
test $0xe0,%cl; |
jnz 0f; |
and $0x1f,%cl; |
shl %cl,%eax; |
and $ERROR_WORD_INTERRUPT_LIST,%eax; |
jz 0f; |
# Return with error word |
restore_all_gpr |
# $8 = Skip error word |
addq $IREGISTER_SPACE + 0x8, %rsp |
addq $(IREGISTER_SPACE+8), %rsp |
iretq |
0: |
# Return with no error word |
restore_all_gpr |
addq $IREGISTER_SPACE, %rsp |
iretq |
.if (\n-\i)-1 |
handler "(\i+1)",\n |
.endif |
/kernel/trunk/arch/amd64/src/interrupt.c |
---|
47,14 → 47,13 |
char *symbol; |
__u64 *x = &istate->stack[0]; |
if (!(symbol=get_symtab_entry(x[1]))) |
if (!(symbol=get_symtab_entry(istate->rip))) |
symbol = ""; |
printf("-----EXCEPTION(%d) OCCURED----- ( %s )\n",n,__FUNCTION__); |
printf("%%rip: %Q (%s)\n",istate->stack[1],symbol); |
printf("ERROR_WORD=%Q\n", istate->stack[0]); |
printf("%%rcs=%Q,flags=%Q, %%cr0=%Q\n", istate->stack[2], |
istate->stack[3],read_cr0()); |
printf("%%rip: %Q (%s)\n",istate->rip, symbol); |
printf("ERROR_WORD=%Q\n", istate->error_word); |
printf("%%rcs=%Q, flags=%Q, %%cr0=%Q\n", istate->cs, istate->rflags,read_cr0()); |
printf("%%rax=%Q, %%rbx=%Q, %%rcx=%Q\n",istate->rax,istate->rbx,istate->rcx); |
printf("%%rdx=%Q, %%rsi=%Q, %%rdi=%Q\n",istate->rdx,istate->rsi,istate->rdi); |
printf("%%r8 =%Q, %%r9 =%Q, %%r10=%Q\n",istate->r8,istate->r9,istate->r10); |
77,9 → 76,7 |
void null_interrupt(int n, istate_t *istate) |
{ |
printf("-----EXCEPTION(%d) OCCURED----- ( %s )\n",n,__FUNCTION__); \ |
printf("stack: %X, %X, %X, %X\n", istate->stack[0], istate->stack[1], |
istate->stack[2], istate->stack[3]); |
print_info_errcode(n, istate); |
panic("unserviced interrupt\n"); |
} |
/kernel/trunk/arch/ia32/src/asm.S |
---|
78,36 → 78,36 |
# and call exc_dispatch(). |
# |
.macro handler i n |
push %eax |
/* |
* Test if this is interrupt with error word or not. |
* Be careful about width of the shift. |
* This macro distinguishes between two versions of ia32 exceptions. |
* One version has error word and the other does not have it. |
* The latter version fakes the error word on the stack so that the |
* handlers and istate_t can be the same for both types. |
*/ |
.iflt \i-32 |
movl $(1<<\i), %eax |
.if (1 << \i) & ERROR_WORD_INTERRUPT_LIST |
/* |
* Version with error word. |
* Just take space equal to subl $4, %esp. |
*/ |
nop |
nop |
nop |
.else |
movl $0, %eax |
.endif |
andl $ERROR_WORD_INTERRUPT_LIST, %eax |
movl (%esp), %eax |
/* |
* If this interrupt/exception stores error word, |
* we need to pop EAX. |
* If this interrupt doesn't store error word, we emulate it |
* for the sake of consistent istate structure. In that case |
* we merely leave the EAX on the stack. |
* Version without error word, |
*/ |
jz 0f |
subl $4, %esp |
.endif |
.else |
/* |
* This exception stores error word. |
* Remove EAX from the stack. |
* Version without error word, |
*/ |
addl $4, %esp |
subl $4, %esp |
.endif |
0: |
pusha |
movl %esp, %ebp |
push %ds |
138,7 → 138,7 |
popfl |
popa |
addl $4,%esp # Skip error word, whether real or fake. |
addl $4,%esp # Skip error word, no matter whether real or fake. |
iret |
.if (\n-\i)-1 |