46,8 → 46,99 |
|
.extern SYMBOL_NAME(periodic_wake_up) |
.extern SYMBOL_NAME(oneshot_wake_up) |
.extern SYMBOL_NAME(ack_APIC_irq) |
|
.text |
.globl SYMBOL_NAME(ll_apic_timer) |
/* APIC ll_timer */ |
|
SYMBOL_NAME_LABEL(ll_apic_timer) |
pushal |
pushw %ds |
pushw %es |
pushw %fs |
pushw %gs |
|
movw $(X_FLATDATA_SEL),%ax |
movw %ax,%ds |
movw %ax,%es |
|
/* Send EOI to APIC */ |
movl $0xFEE000B0,%ebx |
movl $0,(%ebx) |
|
/* Call wake_up(actual_context) */ |
|
movl SYMBOL_NAME(ll_clock),%eax |
incl %eax |
movl %eax,SYMBOL_NAME(ll_clock) |
|
/* The following could be optimized a little... */ |
xorl %ebx, %ebx |
movw %ss, %bx |
/* We must switch to a ``safe stack'' */ |
/* |
* OK, this is the idea: in %esp we have the address of the |
* stack pointer in the APPLICATION address space... |
* We assume that address spaces are implemented through segments... |
* What we have to do is to add the segment base to %esp: |
* - Load the GDT base in a register |
* - Add DS * 8 to that value |
* - Read the corresponding GDT entry (the segment descriptor) |
* - Compute the base... |
* It is (*p & 0xFC) | (*(p +1) & 0x0F) << 16) | *(p + 2) |
*/ |
movl SYMBOL_NAME(GDT_base), %edi |
addl %ebx, %edi |
xorl %ebx, %ebx |
movb 7(%edi), %bh |
movb 4(%edi), %bl |
shl $16, %ebx |
movw 2(%edi), %bx |
/* Is it correct? I think so... Test it!!! */ |
addl %ebx, %esp |
/* Save EBX for returning to our stack... */ |
movw %ds, %cx |
movw %ss, %dx |
movw %cx, %ss |
pushl %ebx |
pushl %edx |
cld |
movl SYMBOL_NAME(timermode), %eax |
cmpl $1, %eax |
je apic_oneshot |
call SYMBOL_NAME(periodic_wake_up) |
jmp apic_Timer_OK |
apic_oneshot: call SYMBOL_NAME(oneshot_wake_up) |
apic_Timer_OK: |
/* Restore ESP */ |
popl %edx |
popl %ebx /* We must subtract it from ESP...*/ |
subl %ebx, %esp |
movw %dx, %ss |
|
#ifdef __VIRCSW__ |
|
movw SYMBOL_NAME(currCtx), %ax |
cmpw %ax,JmpSel |
je apic_NoPreempt2 |
movw %ax,JmpSel |
ljmp JmpZone /* DISPATCH! */ |
#endif |
apic_NoPreempt2: |
|
cmpl $0, SYMBOL_NAME(last_handler) |
je apic_nohandler |
movl SYMBOL_NAME(last_handler), %ebx |
call *%ebx |
apic_nohandler: |
popw %gs |
popw %fs |
popw %es |
popw %ds |
popal |
iret |
|
.globl SYMBOL_NAME(ll_timer) |
/* This is the timer handler; it reloads for safety the DS register; this */ |
/* prevents from mess when timer interrupts linear access to memory (not in */ |