revert between 56095 -> 55830 in arch
[AROS.git] / arch / all-pc / kernel / syscall.c
blobdf5353052cc2395f23189af3cee8cef339cd5d11
1 /*
2 Copyright © 2017-2018, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <asm/cpu.h>
7 #include <asm/io.h>
8 #include <aros/libcall.h>
9 #include <aros/asmcall.h>
10 #include <exec/execbase.h>
11 #include <hardware/intbits.h>
12 #include <proto/exec.h>
14 #include <inttypes.h>
16 #include "kernel_base.h"
17 #include "kernel_debug.h"
18 #include "kernel_globals.h"
19 #include "kernel_interrupts.h"
20 #include "kernel_intern.h"
21 #include "kernel_intr.h"
22 #include "kernel_scheduler.h"
23 #include "kernel_syscall.h"
24 #include "cpu_traps.h"
26 #define D(x)
27 #define DSYSCALL(x)
29 #if (__WORDSIZE != 64)
30 extern void core_Kick(struct TagItem *msg, void *target);
31 extern void kernel_cstart(const struct TagItem *msg);
32 #endif
34 int core_SysCallHandler(struct ExceptionContext *regs, struct KernelBase *KernelBase, void *HandlerData2)
36 struct PlatformData *pdata = KernelBase->kb_PlatformData;
37 struct syscallx86_Handler *scHandler;
38 ULONG sc =
39 #if (__WORDSIZE == 64)
40 regs->rax;
41 #else
42 regs->eax;
43 #endif
44 BOOL systemSysCall = TRUE;
46 /* Syscall number is actually ULONG (we use only eax) */
47 DSYSCALL(bug("[Kernel] %s: Syscall %08x\n", __func__, sc));
49 ForeachNode(&pdata->kb_SysCallHandlers, scHandler)
51 if ((ULONG)((IPTR)scHandler->sc_Node.ln_Name) == sc)
53 DSYSCALL(bug("[Kernel] %s: calling handler @ 0x%p\n", __func__, scHandler));
54 scHandler->sc_SysCall(regs);
55 if (scHandler->sc_Node.ln_Type == 1)
56 systemSysCall = FALSE;
60 if (systemSysCall && INTR_FROMUSERMODE)
62 DSYSCALL(bug("[Kernel] %s: User-mode syscall\n", __func__));
64 /* Disable interrupts for a while */
65 __asm__ __volatile__("cli; cld;");
67 core_SysCall(sc, regs);
70 DSYSCALL(bug("[Kernel] %s: Returning from syscall...\n", __func__));
72 return TRUE;
75 BOOL krnAddSysCallHandler(struct PlatformData *pdata, struct syscallx86_Handler *newscHandler, BOOL custom, BOOL force)
77 struct syscallx86_Handler *scHandler;
79 D(bug("[Kernel] %s(%08x)\n", __func__, newscHandler->sc_Node.ln_Name));
81 /* Unless the 'force' flag is set, bale out if there is already a handler
82 * of the same type (note that we're not comparing strings here - ln_Name
83 * is abused) */
84 if (!force)
86 ForeachNode(&pdata->kb_SysCallHandlers, scHandler)
88 if (scHandler->sc_Node.ln_Name == newscHandler->sc_Node.ln_Name)
89 return FALSE;
93 if (custom)
94 newscHandler->sc_Node.ln_Type = 1;
95 else
96 newscHandler->sc_Node.ln_Type = 0;
98 D(bug("[Kernel] %s: Registering handler...\n", __func__));
99 AddTail(&pdata->kb_SysCallHandlers, &newscHandler->sc_Node);
101 return TRUE;
104 /* Default x86 syscall handlers */
106 void X86_HandleChangePMStateSC(struct ExceptionContext *regs)
108 UBYTE pmState =
109 #if (__WORDSIZE==64)
110 (UBYTE)regs->rbx;
111 #else
112 (UBYTE)regs->ebx;
113 #endif
115 D(bug("[Kernel] %s(0x%02x)\n", __func__, pmState));
117 if (pmState == 0xFF)
119 D(bug("[Kernel] %s: STATE 0xFF - Attempting Cold Reboot...\n", __func__));
122 * On some machines (new PCs without a PS/2 controller), this might
123 * not work.
126 outb(0xFE, 0x64);
128 else if (pmState == 0)
130 D(bug("[Kernel] %s: STATE 0x00 - Halting...\n", __func__));
133 there is no way to power off by default,
134 so just halt the cpu.. */
136 while (1) asm volatile("hlt");
138 else if (pmState == 0x90)
140 /* Sleep almost forever ;) */
141 __asm__ __volatile__("sti; hlt; cli");
143 D(bug("[Kernel] %s: Woke from sleep; checking for softints...\n",
144 __func__);)
145 if (SysBase->SysFlags & SFF_SoftInt)
146 core_Cause(INTB_SOFTINT, 1L << INTB_SOFTINT);
148 else
150 /* We can't handle any other states atm =/ */
151 D(bug("[Kernel] %s: UNHANDLED STATE 0x%02x\n", __func__, pmState));
155 struct syscallx86_Handler x86_SCChangePMStateHandler =
158 .ln_Name = (APTR)SC_X86CHANGEPMSTATE
160 (APTR)X86_HandleChangePMStateSC
163 /* Generic warm-reset handler */
165 void X86_HandleRebootSC()
167 D(bug("[Kernel] %s: Warm restart, stack 0x%p\n", __func__, AROS_GET_SP));
170 * Restart the kernel with a double stack swap. This doesn't return.
171 * Double swap guarantees that core_Kick() is called when SP is set to a
172 * dynamically allocated emergency stack and not to boot stack.
173 * Such situation is rare but can occur in the following situation:
174 * 1. Boot task calls SuperState(). Privilege changed, but stack is manually reset
175 * back into our .bss space.
176 * 2. Boot task crashes. Privilege doesn't change this time, ESP/RSP is not changed.
177 * 3. If we call core_Kick() right now, we are dead (core_Kick() clears .bss).
179 #if (__WORDSIZE == 64)
180 __asm__ __volatile__(
181 "cli\n\t"
182 "cld\n\t"
183 "movq %0, %%rsp\n\t"
184 "jmp *%1\n"
185 ::"r"(__KernBootPrivate->SystemStack + STACK_SIZE), "r"(core_Kick), "D"(BootMsg), "S"(kernel_cstart));
186 #else
187 __asm__ __volatile__(
188 "cli\n\t"
189 "cld\n\t"
190 "movl %0, %%esp\n\t"
191 "pushl %3\n\t"
192 "pushl %2\n\t"
193 "call *%1\n"
194 ::"r"(0x1000), "r"(core_Kick), "r"(BootMsg), "r"(kernel_cstart));
195 #endif
198 struct syscallx86_Handler x86_SCRebootHandler =
201 .ln_Name = (APTR)SC_REBOOT
203 (APTR)X86_HandleRebootSC
206 struct syscallx86_Handler x86_SCSupervisorHandler =
209 .ln_Name = (APTR)SC_SUPERVISOR
211 (APTR)core_Supervisor