Kernel - Signals partially implimented
authorJohn Hodge <[email protected]>
Sat, 16 Feb 2013 09:11:49 +0000 (17:11 +0800)
committerJohn Hodge <[email protected]>
Sat, 16 Feb 2013 09:11:49 +0000 (17:11 +0800)
- No userland bindings, or kernel actions yet

KernelLand/Kernel/arch/x86/desctab.asm
KernelLand/Kernel/arch/x86/proc.asm
KernelLand/Kernel/arch/x86/proc.c
KernelLand/Kernel/include/signal.h
KernelLand/Kernel/include/threads_int.h
KernelLand/Kernel/threads.c

index 18ed10d..354a001 100644 (file)
@@ -220,13 +220,12 @@ Isr240.jmp:
 %assign i i+1
 %endrep
 
+[extern ReturnFromInterrupt]
 ; ---------------------
 ; Common error handling
 ; ---------------------
 [extern ErrorHandler]
 ErrorCommon:
-       ;xchg bx, bx    ; MAGIC BREAK
-       
        pusha
        push ds
        push es
@@ -248,13 +247,7 @@ ErrorCommon:
        call ErrorHandler
        add esp, 4
        
-       pop gs
-       pop fs
-       pop es
-       pop ds
-       popa
-       add esp, 8      ; Error Code and ID
-       iret
+       jmp ReturnFromInterrupt
 
 ; --------------------------
 ; Common System Call Handler
@@ -282,14 +275,8 @@ SyscallCommon:
        and eax, 0x100  ; 0x100 = Trace Flag
        and WORD [esp+(4+8+2+2)*4], ~0x100      ; Clear
        or DWORD [esp+(4+8+2+2)*4], eax ; Set for user
-       
-       pop gs
-       pop fs
-       pop es
-       pop ds
-       popa
-       add esp, 8      ; Error Code and ID
-       iret
+
+       jmp ReturnFromInterrupt 
 
 ; ------------
 ; IRQ Handling
index 8da7971..dcafc5f 100644 (file)
@@ -215,9 +215,9 @@ scheduler_return:   ; Used by some hackery in Proc_DumpThreadCPUState
        
        mov al, 0x20
        out 0x20, al            ; ACK IRQ
+
        %if USE_MP
        jmp .ret
-       
 .sendEOI:
        mov eax, DWORD [gpMP_LocalAPIC]
        mov DWORD [eax+0x0B0], 0
@@ -225,15 +225,60 @@ scheduler_return: ; Used by some hackery in Proc_DumpThreadCPUState
 .ret:
        pop eax ; Debug Register 0, Current Thread
        mov dr0, eax
+       
+       jmp ReturnFromInterrupt
 
+;
+; Returns after an interrupt, restoring the user state
+; - Also handles signal handlers
+;
+[global ReturnFromInterrupt]
+[extern Threads_GetPendingSignal]
+[extern Threads_GetSignalHandler]
+[extern Proc_CallUser]
+ReturnFromInterrupt:
+       ; Check that we're returning to userland
+       test DWORD [esp+(4+8+2+1)*4], 0x07
+       jz .ret ; Kernel interrupted, return
+
+       call Threads_GetPendingSignal
+       ; eax: signal number
+       test eax, eax
+       jz .ret
+       
+       ; There's a signal pending, funtime
+       push eax
+       call Threads_GetSignalHandler
+       ; eax: signal handler
+       pop ecx
+       test eax, eax
+       jz .ret
+       cmp eax, -1
+       jz .default
+       
+       ; (some stack abuse)
+       push User_RestoreState
+       push ecx
+       mov ecx, esp
+       
+       push (2+4+8+2+2)*4      ; Up to and incl. CS
+       push ecx        ; User stack data base
+       push DWORD [ecx+(2+4+8+2+3)*4]  ; User SP
+       push eax        ; handler
+       call Proc_CallUser
+       ; Oh, ... it failed. Default time?
+       add esp, (4+2)*4
+.default:
+       
+
+       ; Fall through to return
+.ret:
        pop gs
        pop fs
        pop es
        pop ds
-       
        popa
-       add esp, 4*2    ; CPU ID + Dummy error code
-       ; No Error code / int num
+       add esp, 2*4    ; IRQ Num / CPU ID + error code
        iret
 
 [extern Proc_Clone]
@@ -286,52 +331,17 @@ Proc_ReturnToUser:
        ; Good thing this can only be called on a user fault.
        ;
        
-       ; Validate user ESP
-       ; - Page Table
-       mov edx, [eax+KSTACK_USERSTATE_SIZE-12] ; User ESP is at top of kstack - 3*4
-       mov ecx, edx
-       shr ecx, 22
-       test BYTE [0xFC3F0000+ecx*4], 1
-       jnz .justKillIt
-       ; - Page
-       mov ecx, edx
-       shr ecx, 12
-       test BYTE [0xFC000000+ecx*4], 1
-       jnz .justKillIt
-       ; Adjust
-       sub edx, 8
-       ; - Page Table
-       mov ecx, edx
-       shr ecx, 22
-       test BYTE [0xFC3F0000+ecx*4], 1
-       jnz .justKillIt
-       ; - Page
-       mov ecx, edx
-       shr ecx, 12
-       test BYTE [0xFC000000+ecx*4], 1
-       jnz .justKillIt
-       
-       ; Get and alter User SP
-       mov edi, edx
-       mov edx, [ebp+12]       ; Get parameter
-       mov [edi+4], edx        ; save to user stack
-       mov [edi], DWORD User_Syscall_RetAndExit        ; Return Address
-       
-       ; Restore Segment Registers
-       mov ax, 0x23
-       mov ds, ax
-       mov es, ax
-       mov fs, ax
-       mov gs, ax
-       
-       push 0x23       ; SS
-       push edi        ; ESP
-       push 0x202      ; EFLAGS (IP and Rsvd)
-       push 0x1B       ; CS
-       mov eax, [ebp+8]        ; Method to call
-       push eax        ; EIP
-       
-       iret
+       ; Create data to add to user stack
+       push DWORD [ebp+12]
+       push User_Syscall_RetAndExit
+       mov ecx, esp
+
+       ; Call user method      
+       push 2*4
+       push ecx
+       push DWORD [eax+KSTACK_USERSTATE_SIZE-12]       ; User ESP is at top of kstack - 3*4
+       push DWORD [ebp+8]
+       call Proc_CallUser      
        
        ; Just kill the bleeding thing
        ; (I know it calls int 0xAC in kernel mode, but meh)
@@ -363,6 +373,16 @@ User_Syscall:
        xchg bx, bx     ; MAGIC BREAKPOINT
        int 0xAC
 
+User_RestoreState:
+       pop gs
+       pop fs
+       pop es
+       pop ds
+       popa
+       add esp, 2*4    ; Kernel's error code and interrupt number
+       retf    ; EFLAGS/SS/ESP were not included in the state
+       
+
 ; A place to return to and exit
 User_Syscall_RetAndExit:
        push eax
index 8b05488..4847d51 100644 (file)
@@ -50,6 +50,7 @@ extern char   scheduler_return[];     // Return address in SchedulerBase
 extern char    IRQCommon[];    // Common IRQ handler code
 extern char    IRQCommon_handled[];    // IRQCommon call return location
 extern char    GetEIP_Sched_ret[];     // GetEIP call return location
+extern void    Timer_CallTimers(void);
 
 // === PROTOTYPES ===
 //void ArchThreads_Init(void);
@@ -67,6 +68,7 @@ void  Proc_ChangeStack(void);
 Uint   Proc_MakeUserStack(void);
 //void Proc_StartUser(Uint Entrypoint, Uint *Bases, int ArgC, char **ArgV, char **EnvP, int DataSize);
 void   Proc_StartProcess(Uint16 SS, Uint Stack, Uint Flags, Uint16 CS, Uint IP) NORETURN;
+void   Proc_CallUser(Uint32 UserIP, Uint32 UserSP, const void *StackData, size_t StackDataLen);
 //void Proc_CallFaultHandler(tThread *Thread);
 //void Proc_DumpThreadCPUState(tThread *Thread);
 void   Proc_Scheduler(int CPU);
@@ -633,6 +635,34 @@ void Proc_StartProcess(Uint16 SS, Uint Stack, Uint Flags, Uint16 CS, Uint IP)
        for(;;);
 }
 
+void Proc_CallUser(Uint32 UserIP, Uint32 UserSP, const void *StackData, size_t StackDataLen)
+{
+       if( UserSP < StackDataLen )
+               return ;
+       if( !CheckMem( (void*)(UserSP - StackDataLen), StackDataLen ) )
+               return ;
+       memcpy( (void*)(UserSP - StackDataLen), StackData, StackDataLen );
+       
+       __asm__ __volatile__ (
+               "mov $0x23,%%ax;\n\t"
+               "mov %%ax, %%ds;\n\t"
+               "mov %%ax, %%es;\n\t"
+               "mov %%ax, %%fs;\n\t"
+               "mov %%ax, %%gs;\n\t"
+               "push $0x23;\n\t"
+               "push %1;\n\t"
+               "push $0x202;\n\t"
+               "push $0x1B;\n\t"
+               "push %0;\n\t"
+               "iret;\n\t"
+               :
+               : "r" (UserIP), "r" (UserSP - StackDataLen)
+               : "eax"
+               );
+       for(;;)
+               ;
+}
+
 /**
  * \brief Calls a signal handler in user mode
  * \note Used for signals
index d97d6dc..3f2a9c4 100644 (file)
@@ -5,12 +5,30 @@
 #ifndef _SIGNAL_H_
 #define _SIGNAL_H_
 
+#define SIG_DFL        NULL
+
 enum eSignals {
-       SIGKILL,
-       SIGSTOP,
-       SIGCONT,
-       SIGCHLD,
-       NSIG
+       SIGNONE =  0,   // No signal
+       SIGHUP  =  1,
+       SIGINT  =  2,   // C
+       SIGQUIT =  3,   // POSIX
+       SIGILL  =  4,   // C
+       SIGTRAP =  5,   // POSIX
+       SIGABRT =  6,   // C?
+       SIGBUS  =  7,   // ?
+       SIGFPE  =  8,   // C
+       SIGKILL =  9,   // POSIX
+       SIGUSR1 = 10,
+       SIGSEGV = 11,   // C
+       SIGUSR2 = 12,
+       SIGPIPE = 13,   // 
+       SIGALRM = 14,
+       SIGTERM = 15,   
+       _SIG16  = 16,
+       SIGCHLD = 17,
+       SIGCONT = 18,
+       SIGSTOP = 19,
+       NSIGNALS
 };
 
 #endif
index 09e58c1..d770668 100644 (file)
@@ -12,6 +12,7 @@
 #include <threads.h>
 #include <proc.h>
 #include <timers_int.h>
+#include <signal.h>
 
 typedef struct sProcess        tProcess;
 
@@ -45,6 +46,8 @@ struct sProcess
         int    MaxFD;
        char    *CurrentWorkingDir;
        char    *RootDir;
+       
+       void    *SignalHandlers[NSIGNALS];
 };
 
 /**
@@ -86,6 +89,10 @@ struct sThread
         int    CurFaultNum;    //!< Current fault number, 0: none
        tVAddr  FaultHandler;   //!< Fault Handler
        
+       
+        int    PendingSignal;  //!< Pending signal ID (0 = none)
+       
+       
        tMsg * volatile Messages;       //!< Message Queue
        tMsg    *LastMessage;   //!< Last Message (speeds up insertion)
        
index 7dd9f6e..007d16f 100644 (file)
@@ -66,6 +66,10 @@ tThread      *Threads_RemActive(void);
 void   Threads_ToggleTrace(int TID);
 void   Threads_Fault(int Num);
 void   Threads_SegFault(tVAddr Addr);
+void   Threads_PostSignal(int SignalNum);
+ int   Threads_GetPendingSignal(void);
+void   Threads_SetSignalHandler(int SignalNum, void *Handler);
+void   *Threads_GetSignalHandler(int SignalNum);
 #if 0
  int   Threads_GetPID(void);
  int   Threads_GetTID(void);
@@ -1004,6 +1008,62 @@ void Threads_SegFault(tVAddr Addr)
        //Threads_Exit( 0, -1 );
 }
 
+
+void Threads_PostSignal(int SignalNum)
+{
+       tThread *cur = Proc_GetCurThread();
+       cur->PendingSignal = SignalNum;
+       Threads_PostEvent(cur, THREAD_EVENT_SIGNAL);
+}
+
+/**
+ */
+int Threads_GetPendingSignal(void)
+{
+       tThread *cur = Proc_GetCurThread();
+       
+       // Atomic AND with 0 fetches and clears in one operation
+       return __sync_fetch_and_and( &cur->PendingSignal, 0 );
+}
+
+/*
+ * \brief Update the current thread's signal handler
+ */
+void Threads_SetSignalHandler(int SignalNum, void *Handler)
+{
+       if( SignalNum <= 0 || SignalNum >= NSIGNALS )
+               return ;
+       if( !MM_IsUser(Handler) )
+               return ;
+       Proc_GetCurThread()->Process->SignalHandlers[SignalNum] = Handler;
+}
+
+/**
+ * \return 0  Ignore
+ */
+void *Threads_GetSignalHandler(int SignalNum)
+{
+       if( SignalNum <= 0 || SignalNum >= NSIGNALS )
+               return NULL;
+       void *ret = Proc_GetCurThread()->Process->SignalHandlers[SignalNum];
+       if( !ret )
+       {
+               // Defaults
+               switch(SignalNum)
+               {
+               case SIGINT:
+               case SIGKILL:
+               case SIGSEGV:
+//                     ret = User_Signal_Kill;
+                       break;
+               default:
+                       ret = NULL;
+                       break;
+               }
+       }
+       return ret;
+}
+
 // --- Process Structure Access Functions ---
 tPGID Threads_GetPGID(void)
 {

UCC git Repository :: git.ucc.asn.au