From e2a6ca9d03a3c0743384f0955609650f2cdce9bb Mon Sep 17 00:00:00 2001 From: Miguel Date: Thu, 18 Oct 2018 06:23:26 +0200 Subject: struggling with new syscalls --- kernel/interrupts.c | 105 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 87 insertions(+), 18 deletions(-) (limited to 'kernel/interrupts.c') diff --git a/kernel/interrupts.c b/kernel/interrupts.c index b7cdd74..8bc4f47 100644 --- a/kernel/interrupts.c +++ b/kernel/interrupts.c @@ -13,6 +13,7 @@ #include "apic.h" #include "ringbuffer.h" #include "compositor.h" +#include "syscalls.h" /** The size of our interrupts table */ #define INT_MAX 256 // 0-255 @@ -51,8 +52,37 @@ static void int_install_ir(int irq, uint16_t flags, uint16_t sel, void *addr) } /** - * Register an interrupt handler for given irq number. + * Register an interrupt handler for a given irq number. + * + * Some general notes on interrupts + * (TODO: consider moving this somewehre else) + * + * 1) In case of a syscall (coming from userspace) the handler should: + * a) For a blocking call, set required params and call the scheduler! + * b) Otherweise call x86_sti() by itself as soon as possiblle to + * reenable interrupts. + * + * 2) In case of APIC Timer interrupt call the scheduler. + * + * 3) Keyboard, Mouse, E1000, PIT + * just push your stuff somewhere for later processing as fast as + * you can and reschedule to a kernel worker OR just iret. + * + * 4) IPI + * we use them to force rescheduling only now + * treated in the same way as a APIC Timer interrupt... + * TODO: NOT CALL THIS IPI!! since we send it only on same cpu now :P + * + * NOTE: apic_eoi() should be called in all cases except the syscalls, + * to signal the "end of interrupt" to the APIC. + * + * TODO: REMEMBER THAT WE WILL HAVE TO CHECK ALL OUR SYSCALL ARE REENTRANT! + * ALSO IN MULTICPU SETTINGS! (check the userspace wrappers as well!) + * EACH prog requires a sufficient kernel-stack as well! (check this!) + * WE CAN GUARD with spinlocks / disabling interrupts when really needed.... + * */ + void interrupt_register(uint32_t irq, uint32_t func_addr) { if(irq<128||irq>160)kpanic("irq number out of range!"); @@ -72,36 +102,75 @@ uint32_t interrupt_handler(uint32_t esp, uint32_t irq) { uint32_t (*f)(uint32_t esp)=handlers[irq]; esp=f(esp); - apic_eoi(); + if(irq!=INTERRUPT_SYSCALL)apic_eoi(); return esp; } - if(irq==INTERRUPT_APIC_TIMER) + if(irq==INTERRUPT_APIC_TIMER || irq==INTERRUPT_IPI) { - if(cpu==0) - { - compositor_wake2(); - scheduler_wake_all(); - scheduler_wake_worker(esp); + if(cpu==0) // thi + { + // limit compositor to APIC_TIMER freq.(60hz?) + if(irq==INTERRUPT_APIC_TIMER)compositor_wake2(); } - } - if(irq==INTERRUPT_APIC_TIMER || irq==INTERRUPT_IPI) - { - esp=scheduler_run(esp,-1); + esp=scheduler_run(esp,-1); // just schedule to next task apic_eoi(); return esp; } if(irq==INTERRUPT_SYSCALL) { - apic_eoi(); + int pid=task_get_current_pid(); + uint32_t *stack; - stack=esp; - task_syscall(stack[11],stack[8],stack[10],stack[9]); //eax,ebx,ecx,edx - scheduler_wake_worker(esp); - esp=scheduler_run(esp,-1); - return esp; + stack=esp; + + // extract variables from stack + // (NOTE we pass them in some fucked up order, + // they were pushed via pusha! + uint32_t eax=stack[11]; + uint32_t ebx=stack[8]; + uint32_t ecx=stack[10]; + uint32_t edx=stack[9]; + + // only chance to do somehting before we reenable interrupts! + syscall_generic_prep(eax,edx,ecx,ebx,pid); + + // now we don't give a shit about gettting interrupted, yeah! + // this is guaranteed to cause heavy troubles... since we are + // not reentrant and do not guard anythin.. + + // keep brute force rescheduling till' we get through.... + // TODO: implement some waiting queue and wake only if there + // is any chance this will not fail again and again and again.. + // TODO: get rid of this big KERNEL LOCK + // it will also not work with SMP + while(true) + { + // x86_cli(); + int ok=syscall_generic_test(eax,edx,ecx,ebx,pid); + // x86_sti(); + if(ok)break; + else __asm__("int $0x81"); + } + + // uff, once we got through we can do the syscall and get out + // of this place... + // x86_cli(); + uint32_t ret=syscall_generic(eax,edx,ecx,ebx,pid); + // x86_sti(); + + stack[12]=0x1; // indicate with 0x1 we WANT to set a return + // value in ebx (0x0 will skip it) + stack[13]=ret; // and THIS is our return value! + + #ifdef LOG_SYSCALLS + klog("syscall ret=0x%08X",ret); + #endif + + //__asm__("int $0x81"); + return esp; // return to asm interrupt handler... and iret. } kpanic("unhandled interrupt %d",irq); -- cgit v1.2.3