336 asm("mov es, ax "); |
336 asm("mov es, ax "); |
337 asm("mov eax, ds:[%0]" : : "i" (X86_LOCAL_APIC_BASE + X86_LOCAL_APIC_OFFSET_ID)); |
337 asm("mov eax, ds:[%0]" : : "i" (X86_LOCAL_APIC_BASE + X86_LOCAL_APIC_OFFSET_ID)); |
338 asm("shr eax, 24 "); |
338 asm("shr eax, 24 "); |
339 asm("mov esi, [eax*4+%0]" : : "i" (&SubSchedulerLookupTable)); |
339 asm("mov esi, [eax*4+%0]" : : "i" (&SubSchedulerLookupTable)); |
340 asm("mov edi, esp "); // edi points to saved stuff |
340 asm("mov edi, esp "); // edi points to saved stuff |
341 asm("inc dword ptr [esi+%0]" : : "i" _FOFF(TSubScheduler, iSSX.iIrqCount)); // increment i_IrqCount |
341 asm("inc dword ptr [esi+36+%0]" : : "i" _FOFF(TSubScheduler, iExtras)); // increment i_IrqCount |
342 asm("inc dword ptr [esi+%0]" : : "i" _FOFF(TSubScheduler, iSSX.iIrqNestCount)); // nest count starts at -1, iExtras[13] |
342 asm("inc dword ptr [esi+52+%0]" : : "i" _FOFF(TSubScheduler, iExtras)); // nest count starts at -1, iExtras[13] |
343 asm("jnz short nested_irq_entry "); |
343 asm("jnz short nested_irq_entry "); |
344 asm("mov esp, [esi+%0]" : : "i" _FOFF(TSubScheduler, iSSX.iIrqStackTop)); // iExtras[14] = irq stack top |
344 asm("mov esp, [esi+56+%0]" : : "i" _FOFF(TSubScheduler, iExtras)); // iExtras[14] = irq stack top |
345 asm("push edi "); |
345 asm("push edi "); |
346 asm("nested_irq_entry: "); |
346 asm("nested_irq_entry: "); |
347 asm("mov edx, [esi+%0]" : : "i" _FOFF(TSubScheduler, iCpuMask)); |
347 asm("mov edx, [esi+%0]" : : "i" _FOFF(TSubScheduler, iCpuMask)); |
348 asm("lock or [%a0], edx" : : "i" (&TheScheduler.iCpusNotIdle)); |
348 asm("lock or [%a0], edx" : : "i" (&TheScheduler.iCpusNotIdle)); |
349 asm("mov ebx, [edi+%0]" : : "i" _FOFF(SThreadExcStack, iVector)); |
349 asm("mov ebx, [edi+%0]" : : "i" _FOFF(SThreadExcStack, iVector)); |
391 asm("add esp, 4 "); |
391 asm("add esp, 4 "); |
392 |
392 |
393 // Postamble. Interrupts disabled here. |
393 // Postamble. Interrupts disabled here. |
394 asm("postamble: "); |
394 asm("postamble: "); |
395 asm("cli "); |
395 asm("cli "); |
396 asm("dec dword ptr [esi+%0]" : : "i" _FOFF(TSubScheduler, iSSX.iIrqNestCount)); |
396 asm("dec dword ptr [esi+52+%0]" : : "i" _FOFF(TSubScheduler, iExtras)); |
397 asm("jns short nested_irq_exit "); |
397 asm("jns short nested_irq_exit "); |
398 |
398 |
399 // Check for deferred/transferred IRQs |
399 // Check for deferred/transferred IRQs |
400 asm("cmp byte ptr [esi+%0], 0 " : : "i" _FOFF(TSubScheduler,iEventHandlersPending)); |
400 asm("cmp byte ptr [esi+%0], 0 " : : "i" _FOFF(TSubScheduler,iEventHandlersPending)); |
401 asm("je short no_event_handlers "); |
401 asm("je short no_event_handlers "); |
402 |
402 |
403 // increment i_IrqNestCount again since we are going to run more ISRs |
403 // increment i_IrqNestCount again since we are going to run more ISRs |
404 asm("inc dword ptr [esi+%0]" : : "i" _FOFF(TSubScheduler, iSSX.iIrqNestCount)); |
404 asm("inc dword ptr [esi+52+%0]" : : "i" _FOFF(TSubScheduler, iExtras)); |
405 asm("push esi "); |
405 asm("push esi "); |
406 asm("call %a0" : : "i" (run_event_handlers)); |
406 asm("call %a0" : : "i" (run_event_handlers)); |
407 asm("add esp, 4 "); |
407 asm("add esp, 4 "); |
408 asm("dec dword ptr [esi+%0]" : : "i" _FOFF(TSubScheduler, iSSX.iIrqNestCount)); |
408 asm("dec dword ptr [esi+52+%0]" : : "i" _FOFF(TSubScheduler, iExtras)); |
409 |
409 |
410 asm("no_event_handlers: "); |
410 asm("no_event_handlers: "); |
411 asm("pop eax "); |
411 asm("pop eax "); |
412 asm("mov esp, eax "); |
412 asm("mov esp, eax "); |
413 asm("cmp dword ptr [esi+%0], 0" : : "i" _FOFF(TSubScheduler, iKernLockCount)); |
413 asm("cmp dword ptr [esi+%0], 0" : : "i" _FOFF(TSubScheduler, iKernLockCount)); |
515 asm("mov cx, %0" : : "i" (KRing0DS)); |
515 asm("mov cx, %0" : : "i" (KRing0DS)); |
516 asm("mov gs, cx "); // exception in user mode -> GS = user mode DS |
516 asm("mov gs, cx "); // exception in user mode -> GS = user mode DS |
517 asm("ring0_exception: "); |
517 asm("ring0_exception: "); |
518 asm("mov [ebp], eax "); |
518 asm("mov [ebp], eax "); |
519 |
519 |
520 asm("cmp dword ptr [esi+%0], -1 " : : "i" _FOFF(TSubScheduler, iSSX.iIrqNestCount)); |
520 asm("cmp dword ptr [esi+52+%0], -1 " : : "i" _FOFF(TSubScheduler, iExtras)); |
521 asm("jnz short fatal_exception_irq "); |
521 asm("jnz short fatal_exception_irq "); |
522 asm("cmp dword ptr [esi+%0], 0 " : : "i" _FOFF(TSubScheduler, iKernLockCount)); |
522 asm("cmp dword ptr [esi+%0], 0 " : : "i" _FOFF(TSubScheduler, iKernLockCount)); |
523 asm("jnz short fatal_exception_locked "); |
523 asm("jnz short fatal_exception_locked "); |
524 asm("sti "); |
524 asm("sti "); |
525 asm("cmp dword ptr [ebp+%0], 7 " : : "i" _FOFF(TX86ExcInfo, iExcId)); // check for device not available |
525 asm("cmp dword ptr [ebp+%0], 7 " : : "i" _FOFF(TX86ExcInfo, iExcId)); // check for device not available |
600 asm("mov bp, ss "); |
600 asm("mov bp, ss "); |
601 asm("mov ds, bp "); |
601 asm("mov ds, bp "); |
602 asm("mov esi, ds:[%0]" : : "i" (X86_LOCAL_APIC_BASE + X86_LOCAL_APIC_OFFSET_ID)); |
602 asm("mov esi, ds:[%0]" : : "i" (X86_LOCAL_APIC_BASE + X86_LOCAL_APIC_OFFSET_ID)); |
603 asm("shr esi, 24 "); |
603 asm("shr esi, 24 "); |
604 asm("mov esi, [esi*4+%0]" : : "i" (&SubSchedulerLookupTable)); // esi -> subscheduler |
604 asm("mov esi, [esi*4+%0]" : : "i" (&SubSchedulerLookupTable)); // esi -> subscheduler |
605 asm("mov ebp, [esi+%0]" : : "i" _FOFF(TSubScheduler, iSSX.iCrashState)); |
605 asm("mov ebp, [esi+44+%0]" : : "i" _FOFF(TSubScheduler, iExtras)); |
606 asm("cmp ebp, 16 "); |
606 asm("cmp ebp, 16 "); |
607 asm("jae nmihook "); |
607 asm("jae nmihook "); |
608 asm("mov ebp, [esi+%0]" : : "i" _FOFF(TSubScheduler, iSSX.iTss)); // points to SCpuData |
608 asm("mov ebp, [esi+60+%0]" : : "i" _FOFF(TSubScheduler, iExtras)); // points to SCpuData |
609 asm("mov edi, %0" : : "i" (addressof_TheScheduler)); |
609 asm("mov edi, %0" : : "i" (addressof_TheScheduler)); |
610 asm("lea ebp, [ebp+%0]" : : "i" _FOFF(SCpuData, iRegs)); |
610 asm("lea ebp, [ebp+%0]" : : "i" _FOFF(SCpuData, iRegs)); |
611 asm("mov [ebp+%0], eax" : : "i" _FOFF(SFullX86RegSet, iEax)); |
611 asm("mov [ebp+%0], eax" : : "i" _FOFF(SFullX86RegSet, iEax)); |
612 asm("mov [ebp+%0], ebx" : : "i" _FOFF(SFullX86RegSet, iEbx)); |
612 asm("mov [ebp+%0], ebx" : : "i" _FOFF(SFullX86RegSet, iEbx)); |
613 asm("mov [ebp+%0], ecx" : : "i" _FOFF(SFullX86RegSet, iEcx)); |
613 asm("mov [ebp+%0], ecx" : : "i" _FOFF(SFullX86RegSet, iEcx)); |
625 asm("mov [ebp+%0], eax" : : "i" _FOFF(SFullX86RegSet, iEs)); |
625 asm("mov [ebp+%0], eax" : : "i" _FOFF(SFullX86RegSet, iEs)); |
626 asm("mov ax, fs "); |
626 asm("mov ax, fs "); |
627 asm("mov [ebp+%0], eax" : : "i" _FOFF(SFullX86RegSet, iFs)); |
627 asm("mov [ebp+%0], eax" : : "i" _FOFF(SFullX86RegSet, iFs)); |
628 asm("mov ax, gs "); |
628 asm("mov ax, gs "); |
629 asm("mov [ebp+%0], eax" : : "i" _FOFF(SFullX86RegSet, iGs)); |
629 asm("mov [ebp+%0], eax" : : "i" _FOFF(SFullX86RegSet, iGs)); |
630 asm("lea ebx, [esi+%0]" : : "i" _FOFF(TSubScheduler, iSSX.iIrqNestCount)); // points to i_IrqNestCount |
630 asm("lea ebx, [esi+52+%0]" : : "i" _FOFF(TSubScheduler, iExtras)); // points to i_IrqNestCount |
631 asm("mov eax, 0x80000000 "); |
631 asm("mov eax, 0x80000000 "); |
632 asm("lock xchg eax, [ebx] "); |
632 asm("lock xchg eax, [ebx] "); |
633 asm("mov [ebp+%0], eax" : : "i" _FOFF(SFullX86RegSet, iIrqNestCount)); |
633 asm("mov [ebp+%0], eax" : : "i" _FOFF(SFullX86RegSet, iIrqNestCount)); |
634 asm("test dl, 3 "); |
634 asm("test dl, 3 "); |
635 asm("jnz short priv_change "); |
635 asm("jnz short priv_change "); |
639 asm("jmp short got_regs "); |
639 asm("jmp short got_regs "); |
640 asm("priv_change: "); |
640 asm("priv_change: "); |
641 asm("pop dword ptr [ebp+%0]" : : "i" _FOFF(SFullX86RegSet, iEsp)); |
641 asm("pop dword ptr [ebp+%0]" : : "i" _FOFF(SFullX86RegSet, iEsp)); |
642 asm("pop dword ptr [ebp+%0]" : : "i" _FOFF(SFullX86RegSet, iSs)); |
642 asm("pop dword ptr [ebp+%0]" : : "i" _FOFF(SFullX86RegSet, iSs)); |
643 asm("got_regs: "); |
643 asm("got_regs: "); |
644 asm("mov dword ptr [esi+%0], 2" : : "i" _FOFF(TSubScheduler, iSSX.iCrashState)); // flag that this CPU is done |
644 asm("mov dword ptr [esi+44+%0], 2" : : "i" _FOFF(TSubScheduler, iExtras)); // flag that this CPU is done |
645 asm("nmi_halt: "); |
645 asm("nmi_halt: "); |
646 asm("cli "); |
646 asm("cli "); |
647 asm("xor eax, eax "); |
647 asm("xor eax, eax "); |
648 asm("push eax "); |
648 asm("push eax "); |
649 asm("push eax "); |
649 asm("push eax "); |
792 // Call from ISR |
792 // Call from ISR |
793 EXPORT_C __NAKED__ TLinAddr X86::IrqReturnAddress() |
793 EXPORT_C __NAKED__ TLinAddr X86::IrqReturnAddress() |
794 { |
794 { |
795 asm("mov eax, ds:[%0]" : : "i" (X86_LOCAL_APIC_BASE + X86_LOCAL_APIC_OFFSET_ID)); |
795 asm("mov eax, ds:[%0]" : : "i" (X86_LOCAL_APIC_BASE + X86_LOCAL_APIC_OFFSET_ID)); |
796 asm("shr eax, 24 "); |
796 asm("shr eax, 24 "); |
797 asm("mov eax, [eax*4+%0]" : : "i" (&SubSchedulerLookupTable)); // esi -> subscheduler |
797 asm("mov eax, [eax*4+%0]" : : "i" (&SubSchedulerLookupTable)); // esi -> subscheduler |
798 asm("mov eax, [eax+%0]" : : "i" _FOFF(TSubScheduler, iSSX.iIrqStackTop)); // eax = i_IrqStackTop |
798 asm("mov eax, [eax+56+%0]" : : "i" _FOFF(TSubScheduler, iExtras)); // eax = i_IrqStackTop |
799 asm("mov eax, [eax-4] "); // saved supervisor stack pointer |
799 asm("mov eax, [eax-4] "); // saved supervisor stack pointer |
800 asm("mov eax, [eax+%0]" : : "i" _FOFF(SThreadExcStack, iEip)); // saved return address from original interrupt |
800 asm("mov eax, [eax+%0]" : : "i" _FOFF(SThreadExcStack, iEip)); // saved return address from original interrupt |
801 asm("ret "); |
801 asm("ret "); |
802 } |
802 } |
803 |
803 |
804 __NAKED__ TUint32 get_cr0() |
804 __NAKED__ TUint32 get_cr0() |
805 { |
805 { |
861 asm("mov esi, %0" : : "i" (addressof_TheSubSchedulers)); |
861 asm("mov esi, %0" : : "i" (addressof_TheSubSchedulers)); |
862 asm("mov ebx, %0" : : "i" (sss)); |
862 asm("mov ebx, %0" : : "i" (sss)); |
863 asm("shr eax, 1 "); |
863 asm("shr eax, 1 "); |
864 asm("jnc short sgi1 "); |
864 asm("jnc short sgi1 "); |
865 asm("sgi2: "); |
865 asm("sgi2: "); |
866 asm("mov ecx, [esi+%0]" : : "i" _FOFF(TSubScheduler, iSSX.iAPICID)); |
866 asm("mov ecx, [esi+48+%0]" : : "i" _FOFF(TSubScheduler, iExtras)); // ss.i_APICID |
867 asm("mov ds:[%0], ecx" : : "i" (X86_LOCAL_APIC_BASE + X86_LOCAL_APIC_OFFSET_ICRH)); |
867 asm("mov ds:[%0], ecx" : : "i" (X86_LOCAL_APIC_BASE + X86_LOCAL_APIC_OFFSET_ICRH)); |
868 asm("mov ds:[%0], edx" : : "i" (X86_LOCAL_APIC_BASE + X86_LOCAL_APIC_OFFSET_ICRL)); |
868 asm("mov ds:[%0], edx" : : "i" (X86_LOCAL_APIC_BASE + X86_LOCAL_APIC_OFFSET_ICRL)); |
869 asm("sgi1: "); |
869 asm("sgi1: "); |
870 asm("add esi, ebx "); |
870 asm("add esi, ebx "); |
871 asm("shr eax, 1 "); |
871 asm("shr eax, 1 "); |