diff --git a/kernel/arch/i686/Syscall.S b/kernel/arch/i686/Syscall.S index 7a31dcd1..92753b81 100644 --- a/kernel/arch/i686/Syscall.S +++ b/kernel/arch/i686/Syscall.S @@ -1,3 +1,57 @@ +// arguments in EAX, EBX, ECX, EDX, ESI, EDI +.global asm_syscall_handler +asm_syscall_handler: + # save segment registers + pushw %ds + pushw %es + pushw %fs + pushw %gs + + # save general purpose registers + pushl %ebx + pushl %ecx + pushl %edx + pushl %edi + pushl %esi + pushl %ebp + + # align stack and push arguments + pushl %esp + addl $32, (%esp) + pushl %edi + pushl %esi + pushl %edx + pushl %ecx + pushl %ebx + pushl %eax + + # load kernel segments + movw $0x10, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + movw $0x28, %ax + movw %ax, %gs + + call cpp_syscall_handler + addl $28, %esp + + # restore general purpose registers + popl %ebp + popl %esi + popl %edi + popl %edx + popl %ecx + popl %ebx + + # restore segment registers + popw %gs + popw %fs + popw %es + popw %ds + + iret + .global sys_fork_trampoline sys_fork_trampoline: pushl %ebp diff --git a/kernel/arch/i686/interrupts.S b/kernel/arch/i686/interrupts.S index 9328ad1f..3a7a8e54 100644 --- a/kernel/arch/i686/interrupts.S +++ b/kernel/arch/i686/interrupts.S @@ -24,22 +24,6 @@ popw %gs .endm -.macro pop_userspace_skip_eax - popl %edi - popl %esi - popl %ebp - addl $4, %esp - popl %ebx - popl %edx - popl %ecx - addl $4, %esp - - popw %ds - popw %es - popw %fs - popw %gs -.endm - isr_stub: push_userspace load_kernel_segments @@ -81,46 +65,21 @@ irq_stub: addl $8, %esp iret -.global asm_reschedule_handler -asm_reschedule_handler: - push_userspace - load_kernel_segments +.global asm_yield_handler +asm_yield_handler: + # This can only be called from kernel, so no segment saving is needed + pushal movl %esp, %eax # interrupt registers ptr - leal 40(%esp), %ebx # interrupt stack ptr + leal 32(%esp), %ebx # interrupt stack ptr - subl $12, %esp + subl $4, %esp pushl %eax pushl %ebx - call cpp_reschedule_handler - addl $20, %esp + call cpp_yield_handler + addl $12, %esp - pop_userspace - iret - -// arguments in EAX, EBX, ECX, EDX, ESI, EDI -.global syscall_asm -syscall_asm: - push_userspace - - subl $8, %esp - - pushl %esp - addl $48, (%esp) - - pushl %edi - pushl %esi - pushl %edx - pushl %ecx - pushl %ebx - pushl %eax - - load_kernel_segments - - call cpp_syscall_handler - addl $36, %esp - - pop_userspace_skip_eax + popal iret .macro isr n @@ -211,3 +170,4 @@ irq 28 irq 29 irq 30 irq 31 +irq 32 diff --git a/kernel/kernel/IDT.cpp b/kernel/kernel/IDT.cpp index 20900ee3..8f8e7206 100644 --- a/kernel/kernel/IDT.cpp +++ b/kernel/kernel/IDT.cpp @@ -332,6 +332,7 @@ done: extern "C" void cpp_yield_handler(InterruptStack* interrupt_stack, InterruptRegisters* interrupt_registers) { ASSERT(!InterruptController::get().is_in_service(IRQ_YIELD)); + ASSERT(!GDT::is_user_segment(interrupt_stack->cs)); Processor::enter_interrupt(interrupt_stack, interrupt_registers); Scheduler::get().irq_reschedule();