Project: OSMain
asm {
USE64
IRQ_VECTORS::
//IDTInit() uses this table
//for the initial vectors.
//Other handlers are set, later,
//with SetIDTEntry().
//See SetIDTEntry Grep
DU4 IRQ00,IRQ01,IRQ02,IRQ03;
DU4 IRQ04,IRQ05,IRQ06,IRQ07;
DU4 IRQ08,IRQ09,IRQ0A,IRQ0B;
DU4 IRQ0C,IRQ0D,IRQ0E,IRQ0F;
DU4 IRQ10,IRQ11,IRQ12,IRQ13;
DU4 IRQ14,IRQ15,IRQ16,IRQ17;
DU4 IRQ18,IRQ19,IRQ1A,IRQ1B;
DU4 IRQ1C,IRQ1D,IRQ1E,IRQ1F;
DU4 IRQ20,IRQ21,IRQ22,IRQ23;
DU4 IRQ24,IRQ25,IRQ26,IRQ27;
DU4 IRQ28,IRQ29,IRQ2A,IRQ2B;
DU4 IRQ2C,IRQ2D,IRQ2E,IRQ2F;
DU4 IRQ30,IRQ31,IRQ32,IRQ33;
DU4 IRQ34;
//Set MAX_INITIAL_IDT if you add more
// ************************************
COUT_PUT_F8:
PUSH_C_REGS
PUSH U8 8[RBP]
CALL _PUT_FLOAT
ADD RSP,8
POP_C_REGS
COUT_RETURN:
RET
COUT_PUT_STR:
PUSH RSI
MOV RSI,RAX
CALL PUT_STR
POP RSI
RET
COUT_JMP_TABLE:
DU8 PUT_HEX_U4;
DU8 PUT_HEX_U4;
DU8 PUT_HEX_U1;
DU8 PUT_HEX_U1;
DU8 PUT_HEX_U2;
DU8 PUT_HEX_U2;
DU8 PUT_HEX_U4;
DU8 PUT_HEX_U4;
DU8 PUT_HEX_U8;
DU8 PUT_HEX_U8;
DU8 COUT_PUT_F8;
DU8 COUT_PUT_F8;
//ptr types
DU8 PUT_HEX_U4;
DU8 PUT_HEX_U4;
DU8 COUT_PUT_STR;
DU8 COUT_PUT_STR;
COUT_JOIN::
OR RBX,RBX
JZ @@100
@@20: MOV RDX,U8 [RBP]
MOV RAX,U8 8[RBP]
CMP RDX,IT_U1+IT_NUM_IT
JBE @@21
MOV RDX,IT_U8
@@21: CALL U8 COUT_JMP_TABLE[RDX*8]
SUB RBP,16
DEC RBX
JNZ @@20
@@100: RET
IRQ30: JMP I4 _MP_CRASH
//I_COUT
//See PrsCout
IRQ31:: PUSH RBP
MOV RBP,RSP
BT U8 24[RBP],RFLAGS_INTERRUPTS
JNC @@I31
STI
@@I31:
MOV RBP,U8 32[RBP]
MOV RBX,RAX //GET ARG CNT
ADD RBX,RBX
LEA RBP,-16[RBP+RBX*8]
MOV RBX,RAX //GET ARG CNT
CALL COUT_JOIN
POP RBP
IRET
//I_COUTLN
IRQ32:: PUSH RBP
MOV RBP,RSP
BT U8 24[RBP],RFLAGS_INTERRUPTS
JNC @@I32
STI
@@I32:
MOV RBP,U8 32[RBP]
MOV RBX,RAX //GET ARG CNT
ADD RBX,RBX
LEA RBP,-16[RBP+RBX*8]
MOV RBX,RAX //GET ARG CNT
CALL COUT_JOIN
PUSH RAX
MOV RAX,CH_CR
CALL PUT_CHAR
MOV RAX,CH_LINE_FEED
CALL PUT_CHAR
POP RAX
POP RBP
IRET
//I_HIBERNATE
IRQ33:
PUSH RAX
XOR RAX,RAX
MOV EAX,U4 LAPIC_EOI
MOV U4 [RAX],0
XOR RAX,RAX
LOCK
BTS U4 GS:CPU_CPU_FLAGS[RAX],CPUf_HIBERNATING
STI
HLT
LOCK
BTR U4 GS:CPU_CPU_FLAGS[RAX],CPUf_HIBERNATING
POP RAX
IRET
//I_WAKE
IRQ34:
PUSH RAX
XOR RAX,RAX
MOV EAX,U4 LAPIC_EOI
MOV U4 [RAX],0
POP RAX
IRET
//I_TIMER
IRQ20: CALL SAVE_CONTEXT //PREEMPTIVE
CLD
MOV RBP,RSP
MOV RBX,U8 [RBP]
MOV U8 TASK_RIP[RSI],RBX
MOV RAX,U8 16[RBP]
MOV U8 TASK_RFLAGS[RSI],RAX
MOV RAX,U8 24[RBP]
MOV U8 TASK_RSP[RSI],RAX
XOR RAX,RAX
MOV RDI,U8 GS:CPU_ADDRESS[RAX]
LOCK
INC U8 CPU_TOTAL_JIFFIES[RDI]
BT U8 TASK_TASK_FLAGS[RSI],TASKf_IDLE
JC @@1a
CMP RBX,U4 IDLE_START
JB @@1
CMP RBX,U4 IDLE_END
JA @@1
@@1a: LOCK
INC U8 CPU_IDLE_POINT_HITS[RDI]
@@1: MOV RAX,U8 CPU_TIMER_IRQ_CHAIN[RDI]
OR RAX,RAX
JZ @@2
PUSH RSI
CALL RAX
ADD RSP,8
CLI
@@2: MOV RAX,U8 CPU_NUM[RDI]
OR RAX,RAX
JZ @@3
XOR RAX,RAX
MOV EAX,U4 LAPIC_EOI
MOV U4 [RAX],0
JMP @@5
@@3: MOV AL,0x20 //ACKNOWLEDGE INTERRUPT
OUT 0x20,AL
@@5: MOV RAX,SYS_SEMAS
BT U4 SYS_SEMA_SINGLE_USER*SEMA_STRUCT_SIZE[RAX],0
JC @@5C
BT U8 TASK_TASK_FLAGS[RSI],TASKf_PREEMPT
JC I4 RESTORE_NEXT_RSI_TASK
@@5C: LOCK
BTR U8 TASK_TASK_FLAGS[RSI],TASKf_HAS_BEEN_SWAPPED
JC @@5B
LOCK
INC U8 CPU_NO_PREEMPT_HITS[RDI]
@@5B: JMP I4 RESTORE_RSI_NO_PREEMPT_TASK
IRQ00:: PUSH 0
JMP IRQFAULT_JMP
IRQ01: PUSH 1
JMP IRQFAULT_JMP
//NMI
IRQ02: HLT
JMP IRQ02
IRQ03: PUSH 3
JMP IRQFAULT_JMP
IRQ04: PUSH 4
JMP IRQFAULT_JMP
IRQ05: PUSH 5
JMP IRQFAULT_JMP
IRQ06: PUSH 6
JMP IRQFAULT_JMP
IRQ07: PUSH 7
JMP IRQFAULT_JMP
IRQ08: PUSH 8
JMP IRQFAULT_JMP
IRQ09: PUSH 9
JMP IRQFAULT_JMP
IRQ0A: PUSH 0x0A
JMP IRQFAULT_JMP
IRQ0B: PUSH 0x0B
JMP IRQFAULT_JMP
IRQ0C: PUSH 0x0C
JMP IRQFAULT_JMP
IRQ0D: PUSH 0x0D
JMP IRQFAULT_JMP
IRQ0E: PUSH 0x0E
JMP IRQFAULT_JMP
IRQ0F: PUSH 0x0F
JMP IRQFAULT_JMP
IRQ10: PUSH 0x10
IRQFAULT_JMP:
JMP IRQFAULT
IRQ11: PUSH 0x11
JMP IRQFAULT
IRQ12: PUSH 0x12
JMP IRQFAULT
IRQ13: PUSH 0x13
JMP IRQFAULT
IRQ14: PUSH 0x14
JMP IRQFAULT
IRQ15: PUSH 0x15
JMP IRQFAULT
IRQ16: PUSH 0x16
JMP IRQFAULT
IRQ17: PUSH 0x17
JMP IRQFAULT
IRQ18: PUSH 0x18
JMP IRQFAULT
IRQ19: PUSH 0x19
JMP IRQFAULT
IRQ1A: PUSH 0x1A
JMP IRQFAULT
IRQ1B: PUSH 0x1B
JMP IRQFAULT
IRQ1C: PUSH 0x1C
JMP IRQFAULT
IRQ1D: PUSH 0x1D
JMP IRQFAULT
IRQ1E: PUSH 0x1E
JMP IRQFAULT
IRQ1F: PUSH 0x1F
JMP IRQFAULT
IRQ21: PUSH 0x21
JMP IRQFAULT
IRQ22: PUSH 0x22
JMP IRQFAULT
IRQ23: PUSH 0x23
JMP IRQFAULT
IRQ24: PUSH 0x24
JMP IRQFAULT
IRQ25: PUSH 0x25
JMP IRQFAULT
IRQ26: PUSH 0x26
JMP IRQFAULT
//This might be a spurious interrupt
//TODO: Why is this needed?
IRQ27: PUSH RAX
MOV AL,0x20
OUT 0x20,AL
POP RAX
IRET
IRQ28: PUSH 0x28
JMP IRQFAULT
IRQ29: PUSH 0x29
JMP IRQFAULT
IRQ2A: PUSH 0x2A
JMP IRQFAULT
IRQ2B: PUSH 0x2B
JMP IRQFAULT
IRQ2C: PUSH 0x2C
JMP IRQFAULT
IRQ2D: PUSH 0x2D
JMP IRQFAULT
IRQ2E: PUSH 0x2E
JMP IRQFAULT
IRQ2F: PUSH 0x2F
JMP IRQFAULT
// ************************************
IRQFAULT::
PUSH RBX
MOV RBX,U8 8[RSP]
PUSH RAX
XOR RAX,RAX
MOV FS:U4 TASK_FAULT_NUM[RAX],EBX
POP RAX
POP RBX
ADD RSP,8
CALL SAVE_CONTEXT
XOR RDX,RDX
MOV U8 TASK_FAULT_ERR_CODE[RSI],RDX
MOV EDX,U4 TASK_FAULT_NUM[RSI]
BT U8 [FAULT_ERR_CODE_BITMAP],RDX
JNC @@1
POP U8 TASK_FAULT_ERR_CODE[RSI]
@@1: MOV RBP,RSP
MOV RAX,U8 [RBP]
MOV U8 TASK_RIP[RSI],RAX
MOV RAX,U8 16[RBP]
MOV U8 TASK_RFLAGS[RSI],RAX
MOV RAX,U8 24[RBP]
MOV U8 TASK_RSP[RSI],RAX
MOV RSP,RAX
MOV RBP,TASK_RBP[RSI]
MOV RSI,TASK_RSI[RSI]
CALL _FAULT2 //See _FAULT2
JMP I4 RESTORE_FS_TASK_WITH_KEY_CHECK
FAULT_ERR_CODE_BITMAP::
DU4 0x00027D00;
}
asm {_INIT_IDT::}
U0 IDTInit()
{ //interrupt descriptor table
U8 i,temp_ptr[2];
U4 *src=IRQ_VECTORS,*dst;
dst=Gs->idt=CAlloc(16*256);
for (i=0;i<MAX_INITIAL_IDT;i++) {
*dst><(U2 *)++=*src><(U2 *)++;
*dst><(U2 *)++=SYS_CS64_SEL;
*dst><(U2 *)++=0x8E00; //E=32-bit irq gate
*dst><(U2 *)++=*src><(U2 *)++;
*dst><(U8 *)++=0;
}
dst=temp_ptr;
*dst><(U2 *)++=256*16-1;
*dst><(U4 *)++=Gs->idt><(U8).u4[0];
*dst><(U4 *)++=Gs->idt><(U8).u4[1];
*dst><(U2 *)++=0;
SetRAX(temp_ptr);
asm {
LIDT U8 [RAX]
}
}
U0 *GetIDTEntry(U8 irq,U8 core_num)
{
U8 result,*src=cpu_structs[core_num].idt><(U1 *)+irq*16;
result.u2[0]=*src><(U2 *);
src><(U1 *)+=6;
result.u2[1]=*src><(U2 *)++;
result.u4[1]=*src><(U4 *);
return result;
}
U0 *SetIDTEntry(U8 irq,U0 (*fp_new_handler)(),U8 core_num)
{
//See ::/LT/Doc/Lectures/Interrupts.CPZ
//See ::/LT/Demo/MultiCore/Interrupts.CPZ
U8 result=GetIDTEntry(irq,core_num);
U1 *dst=cpu_structs[core_num].idt><(U1 *)+irq*16;
*dst><(U2 *)++=fp_new_handler><(U8).u2[0];
*dst><(U2 *)++=SYS_CS64_SEL;
*dst><(U2 *)++=0x8E00; //E=32-bit irq gate
*dst><(U2 *)++=fp_new_handler><(U8).u2[1];
*dst><(U4 *)++=fp_new_handler><(U8).u4[1];
*dst><(U4 *)++=0;
return result;
}