1/*
2 * Copyright 2014, General Dynamics C4 Systems
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 */
6
7#include <config.h>
8#include <machine/assembler.h>
9
10/* From <arch/mode/machine/registerset.h> */
11#define Error              9
12#define NextIP             10
13#define CS                 11
14#define FLAGS              12
15#define ESP                13
16#define n_contextRegisters 17
17
18# On kernel entry, ESP points to the end of the thread's registers array.
19# Hardware pushes onto the stack SS, ESP, EFLAGS, CS, NextIP and Error,
20# leaving the stack pointer pointing to TLS_BASE. The kernel pushes the rest.
21
22#define INT_HANDLER_COMMON(number, error_code) \
23.global int_##number;                        \
24.type int_##number, %function;               \
25int_##number:                                \
26    error_code;                              \
27    pushl 4(%esp); /* FaultIP := NextIP */   \
28    pushl %ebp;                              \
29    pushl %edi;                              \
30    pushl %esi;                              \
31    pushl %edx;                              \
32    pushl %ecx;                              \
33    pushl %ebx;                              \
34    pushl %eax;                              \
35    pushl $0;                                \
36    movl  $0x##number, %ecx;                 \
37    jmp   handle_interrupt;                  \
38    .size int_##number, .-int_##number;
39
40#define INT_HANDLER_WITH_ERR_CODE(number) INT_HANDLER_COMMON(number,)
41#define INT_HANDLER_WITHOUT_ERR_CODE(number) INT_HANDLER_COMMON(number,pushl $0x0)
42
43#ifdef ENABLE_SMP_SUPPORT
44#define SET_KERNEL_STACK_FROM(x)            \
45    movl    (x)(%esp), %esp
46#else
47#define SET_KERNEL_STACK_FROM(x)            \
48    leal kernel_stack_alloc + (1 << CONFIG_KERNEL_STACK_BITS) - 4, %esp
49#endif
50
51#define SET_KERNEL_STACK SET_KERNEL_STACK_FROM(4 * n_contextRegisters)
52
53# switch to the user data segments as the rest of our entry/exit code assumes that's
54# what they will be
55
56#define SET_SELECTOR(selector, value, tmp) \
57    movl %selector, %tmp; \
58    cmpl $value, %tmp; \
59    je 1f; \
60    movl $value, %tmp; \
61    movl %tmp, %selector; \
62    1:
63
64/* user-level selectors from </arch/mode/object/structures.h> */
65#define GDT_DS_0    2
66#define GDT_DS_3    4
67#define GDT_FS      6
68#define GDT_GS      7
69
70/* user-level selectors from </arch/object/structures.h> */
71#define SEL_CS_3    ((GDT_CS_3 << 3) | 3)
72#define SEL_DS_3    ((GDT_DS_3 << 3) | 3)
73#define SEL_FS      ((GDT_FS << 3) | 3)
74#define SEL_GS      ((GDT_GS << 3) | 3)
75
76#define RESET_SELECTORS(tmp) \
77    SET_SELECTOR(ds, SEL_DS_3, tmp) \
78    SET_SELECTOR(es, SEL_DS_3, tmp) \
79    SET_SELECTOR(fs, SEL_FS, tmp) \
80    SET_SELECTOR(gs, SEL_GS, tmp)
81
82.section .text
83
84INT_HANDLER_WITHOUT_ERR_CODE(00)
85INT_HANDLER_WITHOUT_ERR_CODE(01)
86INT_HANDLER_WITHOUT_ERR_CODE(02)
87INT_HANDLER_WITHOUT_ERR_CODE(03)
88INT_HANDLER_WITHOUT_ERR_CODE(04)
89INT_HANDLER_WITHOUT_ERR_CODE(05)
90INT_HANDLER_WITHOUT_ERR_CODE(06)
91INT_HANDLER_WITHOUT_ERR_CODE(07)
92INT_HANDLER_WITH_ERR_CODE(08)
93INT_HANDLER_WITHOUT_ERR_CODE(09)
94INT_HANDLER_WITH_ERR_CODE(0a)
95INT_HANDLER_WITH_ERR_CODE(0b)
96INT_HANDLER_WITH_ERR_CODE(0c)
97INT_HANDLER_WITH_ERR_CODE(0d)
98INT_HANDLER_WITH_ERR_CODE(0e)
99INT_HANDLER_WITHOUT_ERR_CODE(0f)
100
101INT_HANDLER_WITHOUT_ERR_CODE(10)
102INT_HANDLER_WITH_ERR_CODE(11)
103INT_HANDLER_WITHOUT_ERR_CODE(12)
104INT_HANDLER_WITHOUT_ERR_CODE(13)
105INT_HANDLER_WITHOUT_ERR_CODE(14)
106INT_HANDLER_WITHOUT_ERR_CODE(15)
107INT_HANDLER_WITHOUT_ERR_CODE(16)
108INT_HANDLER_WITHOUT_ERR_CODE(17)
109INT_HANDLER_WITHOUT_ERR_CODE(18)
110INT_HANDLER_WITHOUT_ERR_CODE(19)
111INT_HANDLER_WITHOUT_ERR_CODE(1a)
112INT_HANDLER_WITHOUT_ERR_CODE(1b)
113INT_HANDLER_WITHOUT_ERR_CODE(1c)
114INT_HANDLER_WITHOUT_ERR_CODE(1d)
115INT_HANDLER_WITHOUT_ERR_CODE(1e)
116INT_HANDLER_WITHOUT_ERR_CODE(1f)
117
118INT_HANDLER_WITHOUT_ERR_CODE(20)
119INT_HANDLER_WITHOUT_ERR_CODE(21)
120INT_HANDLER_WITHOUT_ERR_CODE(22)
121INT_HANDLER_WITHOUT_ERR_CODE(23)
122INT_HANDLER_WITHOUT_ERR_CODE(24)
123INT_HANDLER_WITHOUT_ERR_CODE(25)
124INT_HANDLER_WITHOUT_ERR_CODE(26)
125INT_HANDLER_WITHOUT_ERR_CODE(27)
126INT_HANDLER_WITHOUT_ERR_CODE(28)
127INT_HANDLER_WITHOUT_ERR_CODE(29)
128INT_HANDLER_WITHOUT_ERR_CODE(2a)
129INT_HANDLER_WITHOUT_ERR_CODE(2b)
130INT_HANDLER_WITHOUT_ERR_CODE(2c)
131INT_HANDLER_WITHOUT_ERR_CODE(2d)
132INT_HANDLER_WITHOUT_ERR_CODE(2e)
133INT_HANDLER_WITHOUT_ERR_CODE(2f)
134
135INT_HANDLER_WITHOUT_ERR_CODE(30)
136INT_HANDLER_WITHOUT_ERR_CODE(31)
137INT_HANDLER_WITHOUT_ERR_CODE(32)
138INT_HANDLER_WITHOUT_ERR_CODE(33)
139INT_HANDLER_WITHOUT_ERR_CODE(34)
140INT_HANDLER_WITHOUT_ERR_CODE(35)
141INT_HANDLER_WITHOUT_ERR_CODE(36)
142INT_HANDLER_WITHOUT_ERR_CODE(37)
143INT_HANDLER_WITHOUT_ERR_CODE(38)
144INT_HANDLER_WITHOUT_ERR_CODE(39)
145INT_HANDLER_WITHOUT_ERR_CODE(3a)
146INT_HANDLER_WITHOUT_ERR_CODE(3b)
147INT_HANDLER_WITHOUT_ERR_CODE(3c)
148INT_HANDLER_WITHOUT_ERR_CODE(3d)
149INT_HANDLER_WITHOUT_ERR_CODE(3e)
150INT_HANDLER_WITHOUT_ERR_CODE(3f)
151
152INT_HANDLER_WITHOUT_ERR_CODE(40)
153INT_HANDLER_WITHOUT_ERR_CODE(41)
154INT_HANDLER_WITHOUT_ERR_CODE(42)
155INT_HANDLER_WITHOUT_ERR_CODE(43)
156INT_HANDLER_WITHOUT_ERR_CODE(44)
157INT_HANDLER_WITHOUT_ERR_CODE(45)
158INT_HANDLER_WITHOUT_ERR_CODE(46)
159INT_HANDLER_WITHOUT_ERR_CODE(47)
160INT_HANDLER_WITHOUT_ERR_CODE(48)
161INT_HANDLER_WITHOUT_ERR_CODE(49)
162INT_HANDLER_WITHOUT_ERR_CODE(4a)
163INT_HANDLER_WITHOUT_ERR_CODE(4b)
164INT_HANDLER_WITHOUT_ERR_CODE(4c)
165INT_HANDLER_WITHOUT_ERR_CODE(4d)
166INT_HANDLER_WITHOUT_ERR_CODE(4e)
167INT_HANDLER_WITHOUT_ERR_CODE(4f)
168
169INT_HANDLER_WITHOUT_ERR_CODE(50)
170INT_HANDLER_WITHOUT_ERR_CODE(51)
171INT_HANDLER_WITHOUT_ERR_CODE(52)
172INT_HANDLER_WITHOUT_ERR_CODE(53)
173INT_HANDLER_WITHOUT_ERR_CODE(54)
174INT_HANDLER_WITHOUT_ERR_CODE(55)
175INT_HANDLER_WITHOUT_ERR_CODE(56)
176INT_HANDLER_WITHOUT_ERR_CODE(57)
177INT_HANDLER_WITHOUT_ERR_CODE(58)
178INT_HANDLER_WITHOUT_ERR_CODE(59)
179INT_HANDLER_WITHOUT_ERR_CODE(5a)
180INT_HANDLER_WITHOUT_ERR_CODE(5b)
181INT_HANDLER_WITHOUT_ERR_CODE(5c)
182INT_HANDLER_WITHOUT_ERR_CODE(5d)
183INT_HANDLER_WITHOUT_ERR_CODE(5e)
184INT_HANDLER_WITHOUT_ERR_CODE(5f)
185
186INT_HANDLER_WITHOUT_ERR_CODE(60)
187INT_HANDLER_WITHOUT_ERR_CODE(61)
188INT_HANDLER_WITHOUT_ERR_CODE(62)
189INT_HANDLER_WITHOUT_ERR_CODE(63)
190INT_HANDLER_WITHOUT_ERR_CODE(64)
191INT_HANDLER_WITHOUT_ERR_CODE(65)
192INT_HANDLER_WITHOUT_ERR_CODE(66)
193INT_HANDLER_WITHOUT_ERR_CODE(67)
194INT_HANDLER_WITHOUT_ERR_CODE(68)
195INT_HANDLER_WITHOUT_ERR_CODE(69)
196INT_HANDLER_WITHOUT_ERR_CODE(6a)
197INT_HANDLER_WITHOUT_ERR_CODE(6b)
198INT_HANDLER_WITHOUT_ERR_CODE(6c)
199INT_HANDLER_WITHOUT_ERR_CODE(6d)
200INT_HANDLER_WITHOUT_ERR_CODE(6e)
201INT_HANDLER_WITHOUT_ERR_CODE(6f)
202
203INT_HANDLER_WITHOUT_ERR_CODE(70)
204INT_HANDLER_WITHOUT_ERR_CODE(71)
205INT_HANDLER_WITHOUT_ERR_CODE(72)
206INT_HANDLER_WITHOUT_ERR_CODE(73)
207INT_HANDLER_WITHOUT_ERR_CODE(74)
208INT_HANDLER_WITHOUT_ERR_CODE(75)
209INT_HANDLER_WITHOUT_ERR_CODE(76)
210INT_HANDLER_WITHOUT_ERR_CODE(77)
211INT_HANDLER_WITHOUT_ERR_CODE(78)
212INT_HANDLER_WITHOUT_ERR_CODE(79)
213INT_HANDLER_WITHOUT_ERR_CODE(7a)
214INT_HANDLER_WITHOUT_ERR_CODE(7b)
215INT_HANDLER_WITHOUT_ERR_CODE(7c)
216INT_HANDLER_WITHOUT_ERR_CODE(7d)
217INT_HANDLER_WITHOUT_ERR_CODE(7e)
218INT_HANDLER_WITHOUT_ERR_CODE(7f)
219
220INT_HANDLER_WITHOUT_ERR_CODE(80)
221INT_HANDLER_WITHOUT_ERR_CODE(81)
222INT_HANDLER_WITHOUT_ERR_CODE(82)
223INT_HANDLER_WITHOUT_ERR_CODE(83)
224INT_HANDLER_WITHOUT_ERR_CODE(84)
225INT_HANDLER_WITHOUT_ERR_CODE(85)
226INT_HANDLER_WITHOUT_ERR_CODE(86)
227INT_HANDLER_WITHOUT_ERR_CODE(87)
228INT_HANDLER_WITHOUT_ERR_CODE(88)
229INT_HANDLER_WITHOUT_ERR_CODE(89)
230INT_HANDLER_WITHOUT_ERR_CODE(8a)
231INT_HANDLER_WITHOUT_ERR_CODE(8b)
232INT_HANDLER_WITHOUT_ERR_CODE(8c)
233INT_HANDLER_WITHOUT_ERR_CODE(8d)
234INT_HANDLER_WITHOUT_ERR_CODE(8e)
235INT_HANDLER_WITHOUT_ERR_CODE(8f)
236
237INT_HANDLER_WITHOUT_ERR_CODE(90)
238INT_HANDLER_WITHOUT_ERR_CODE(91)
239INT_HANDLER_WITHOUT_ERR_CODE(92)
240INT_HANDLER_WITHOUT_ERR_CODE(93)
241INT_HANDLER_WITHOUT_ERR_CODE(94)
242INT_HANDLER_WITHOUT_ERR_CODE(95)
243INT_HANDLER_WITHOUT_ERR_CODE(96)
244INT_HANDLER_WITHOUT_ERR_CODE(97)
245INT_HANDLER_WITHOUT_ERR_CODE(98)
246INT_HANDLER_WITHOUT_ERR_CODE(99)
247INT_HANDLER_WITHOUT_ERR_CODE(9a)
248INT_HANDLER_WITHOUT_ERR_CODE(9b)
249INT_HANDLER_WITHOUT_ERR_CODE(9c)
250INT_HANDLER_WITHOUT_ERR_CODE(9d)
251INT_HANDLER_WITHOUT_ERR_CODE(9e)
252INT_HANDLER_WITHOUT_ERR_CODE(9f)
253
254INT_HANDLER_WITHOUT_ERR_CODE(a0)
255INT_HANDLER_WITHOUT_ERR_CODE(a1)
256INT_HANDLER_WITHOUT_ERR_CODE(a2)
257INT_HANDLER_WITHOUT_ERR_CODE(a3)
258INT_HANDLER_WITHOUT_ERR_CODE(a4)
259INT_HANDLER_WITHOUT_ERR_CODE(a5)
260INT_HANDLER_WITHOUT_ERR_CODE(a6)
261INT_HANDLER_WITHOUT_ERR_CODE(a7)
262INT_HANDLER_WITHOUT_ERR_CODE(a8)
263INT_HANDLER_WITHOUT_ERR_CODE(a9)
264INT_HANDLER_WITHOUT_ERR_CODE(aa)
265INT_HANDLER_WITHOUT_ERR_CODE(ab)
266INT_HANDLER_WITHOUT_ERR_CODE(ac)
267INT_HANDLER_WITHOUT_ERR_CODE(ad)
268INT_HANDLER_WITHOUT_ERR_CODE(ae)
269INT_HANDLER_WITHOUT_ERR_CODE(af)
270
271INT_HANDLER_WITHOUT_ERR_CODE(b0)
272INT_HANDLER_WITHOUT_ERR_CODE(b1)
273INT_HANDLER_WITHOUT_ERR_CODE(b2)
274INT_HANDLER_WITHOUT_ERR_CODE(b3)
275INT_HANDLER_WITHOUT_ERR_CODE(b4)
276INT_HANDLER_WITHOUT_ERR_CODE(b5)
277INT_HANDLER_WITHOUT_ERR_CODE(b6)
278INT_HANDLER_WITHOUT_ERR_CODE(b7)
279INT_HANDLER_WITHOUT_ERR_CODE(b8)
280INT_HANDLER_WITHOUT_ERR_CODE(b9)
281INT_HANDLER_WITHOUT_ERR_CODE(ba)
282INT_HANDLER_WITHOUT_ERR_CODE(bb)
283INT_HANDLER_WITHOUT_ERR_CODE(bc)
284INT_HANDLER_WITHOUT_ERR_CODE(bd)
285INT_HANDLER_WITHOUT_ERR_CODE(be)
286INT_HANDLER_WITHOUT_ERR_CODE(bf)
287
288INT_HANDLER_WITHOUT_ERR_CODE(c0)
289INT_HANDLER_WITHOUT_ERR_CODE(c1)
290INT_HANDLER_WITHOUT_ERR_CODE(c2)
291INT_HANDLER_WITHOUT_ERR_CODE(c3)
292INT_HANDLER_WITHOUT_ERR_CODE(c4)
293INT_HANDLER_WITHOUT_ERR_CODE(c5)
294INT_HANDLER_WITHOUT_ERR_CODE(c6)
295INT_HANDLER_WITHOUT_ERR_CODE(c7)
296INT_HANDLER_WITHOUT_ERR_CODE(c8)
297INT_HANDLER_WITHOUT_ERR_CODE(c9)
298INT_HANDLER_WITHOUT_ERR_CODE(ca)
299INT_HANDLER_WITHOUT_ERR_CODE(cb)
300INT_HANDLER_WITHOUT_ERR_CODE(cc)
301INT_HANDLER_WITHOUT_ERR_CODE(cd)
302INT_HANDLER_WITHOUT_ERR_CODE(ce)
303INT_HANDLER_WITHOUT_ERR_CODE(cf)
304
305INT_HANDLER_WITHOUT_ERR_CODE(d0)
306INT_HANDLER_WITHOUT_ERR_CODE(d1)
307INT_HANDLER_WITHOUT_ERR_CODE(d2)
308INT_HANDLER_WITHOUT_ERR_CODE(d3)
309INT_HANDLER_WITHOUT_ERR_CODE(d4)
310INT_HANDLER_WITHOUT_ERR_CODE(d5)
311INT_HANDLER_WITHOUT_ERR_CODE(d6)
312INT_HANDLER_WITHOUT_ERR_CODE(d7)
313INT_HANDLER_WITHOUT_ERR_CODE(d8)
314INT_HANDLER_WITHOUT_ERR_CODE(d9)
315INT_HANDLER_WITHOUT_ERR_CODE(da)
316INT_HANDLER_WITHOUT_ERR_CODE(db)
317INT_HANDLER_WITHOUT_ERR_CODE(dc)
318INT_HANDLER_WITHOUT_ERR_CODE(dd)
319INT_HANDLER_WITHOUT_ERR_CODE(de)
320INT_HANDLER_WITHOUT_ERR_CODE(df)
321
322INT_HANDLER_WITHOUT_ERR_CODE(e0)
323INT_HANDLER_WITHOUT_ERR_CODE(e1)
324INT_HANDLER_WITHOUT_ERR_CODE(e2)
325INT_HANDLER_WITHOUT_ERR_CODE(e3)
326INT_HANDLER_WITHOUT_ERR_CODE(e4)
327INT_HANDLER_WITHOUT_ERR_CODE(e5)
328INT_HANDLER_WITHOUT_ERR_CODE(e6)
329INT_HANDLER_WITHOUT_ERR_CODE(e7)
330INT_HANDLER_WITHOUT_ERR_CODE(e8)
331INT_HANDLER_WITHOUT_ERR_CODE(e9)
332INT_HANDLER_WITHOUT_ERR_CODE(ea)
333INT_HANDLER_WITHOUT_ERR_CODE(eb)
334INT_HANDLER_WITHOUT_ERR_CODE(ec)
335INT_HANDLER_WITHOUT_ERR_CODE(ed)
336INT_HANDLER_WITHOUT_ERR_CODE(ee)
337INT_HANDLER_WITHOUT_ERR_CODE(ef)
338
339INT_HANDLER_WITHOUT_ERR_CODE(f0)
340INT_HANDLER_WITHOUT_ERR_CODE(f1)
341INT_HANDLER_WITHOUT_ERR_CODE(f2)
342INT_HANDLER_WITHOUT_ERR_CODE(f3)
343INT_HANDLER_WITHOUT_ERR_CODE(f4)
344INT_HANDLER_WITHOUT_ERR_CODE(f5)
345INT_HANDLER_WITHOUT_ERR_CODE(f6)
346INT_HANDLER_WITHOUT_ERR_CODE(f7)
347INT_HANDLER_WITHOUT_ERR_CODE(f8)
348INT_HANDLER_WITHOUT_ERR_CODE(f9)
349INT_HANDLER_WITHOUT_ERR_CODE(fa)
350INT_HANDLER_WITHOUT_ERR_CODE(fb)
351INT_HANDLER_WITHOUT_ERR_CODE(fc)
352INT_HANDLER_WITHOUT_ERR_CODE(fd)
353INT_HANDLER_WITHOUT_ERR_CODE(fe)
354INT_HANDLER_WITHOUT_ERR_CODE(ff)
355
356handle_interrupt:
357    # Reset segment selectors
358    RESET_SELECTORS(edx)
359
360    # determine if we have a kernel exception
361    testl   $3, (4 * CS)(%esp)     # extract CPL (current privilege level)
362    jz kernel_interrupt
363
364user_interrupt:
365    # switch to kernel stack
366    SET_KERNEL_STACK
367
368    # Place the arguments on the stack
369    pushl   %eax
370    pushl   %ecx
371
372    # gtfo to C land, we will not return
373    call    c_handle_interrupt
374
375kernel_interrupt:
376    cmpl    $0x20, %ecx      # if interrupt vector is below 0x20, we have an exception
377    jl kernel_exception
378    # Check the current ESP. If this is within the bounds of __idle_thread_start and
379    # __idle_thread_end then this is the idle thread. Interrupts from the idle thread
380    # are handled like normal interrupts.
381    cmpl $__idle_thread_start, %esp
382    jb not_idle_thread
383    cmpl $__idle_thread_end, %esp
384    jae not_idle_thread
385    jmp user_interrupt
386not_idle_thread:
387    # We got an interrupt from the kernel. Call into C to save
388    # the IRQ number, then return back to where we were
389    pushl %ecx
390    call c_nested_interrupt
391    addl $4, %esp
392    # Disable the interrupt flag so that we do not take any additional interrupts
393    andl $~0x200, (4 * FLAGS)(%esp)
394    # Return
395kernel_int_return:
396    addl    $4, %esp
397    popl    %eax
398    popl    %ebx
399    popl    %ecx
400    popl    %edx
401    popl    %esi
402    popl    %edi
403    popl    %ebp
404    /* Skip FaultIP and error-code. */
405    addl    $8, %esp
406    iretl
407
408# Handle a kernel exception
409
410BEGIN_FUNC(kernel_exception)
411#ifdef CONFIG_HARDWARE_DEBUG_API
412    /* Before giving up and panicking, we need to test for the extra case that
413     * this might be a kernel exception that is the result of EFLAGS.TF being
414     * set when SYSENTER was called.
415     *
416     * Since EFLAGS.TF is not disabled by SYSENTER, single-stepping continues
417     * into the kernel, and so causes a debug-exception in kernel code, since
418     * the CPU is trying to single-step the kernel code.
419     *
420     * So we test for EFLAGS.TF, and if it's set, we unset it, and let the
421     * exception continue. The debug exception handler will notice that it was
422     * kernel exception, and handle it appropriately -- that really just means
423     * setting EFLAGS.TF before SYSEXIT so that single-stepping resumes in the
424     * userspace thread.
425     */
426    movl    (4 * FLAGS)(%esp), %eax
427    movl    $(1<<8), %ebx
428    testl   %ebx, %eax
429    je      .not_eflags_tf
430
431    /* Else it was EFLAGS.TF that caused the kernel exception on SYSENTER.
432     * So, unset the EFLAGS.TF on the stack and this causes the syscall that we
433     * will return to, to be able to execute properly.
434     *
435     * It will then be the debug exception handler's responsibility to re-set
436     * EFLAGS.TF for the userspace thread before it returns.
437     *
438     * So at this point we want to just unset EFLAGS.TF and IRET immediately.
439     */
440    andl    $~(1<<8), %eax
441    movl    %eax, (4 * FLAGS)(%esp)
442
443    /* Begin popping registers to IRET now. We don't need to consider any
444     * unexpected side effects because we are just immediately returning after
445     * entering.
446     */
447    addl    $4, %esp
448    popl    %eax
449    popl    %ebx
450    popl    %ecx
451    popl    %edx
452    popl    %esi
453    popl    %edi
454    popl    %ebp
455    /* Skip FaultIP and error-code. */
456    addl    $8, %esp
457    iretl
458
459.not_eflags_tf:
460#endif /* CONFIG_HARDWARE_DEBUG_API */
461
462    # prepare debug info
463    movl    (4 * Error)(%esp), %eax # EAX contains Error Code
464    movl    (4 * NextIP)(%esp), %ebx # EBX contains EIP of the exception generating instruction
465    movl    (4 * FLAGS)(%esp), %edx # EDX contains EFLAGS
466    leal    (4 * ESP)(%esp), %edi # EDI contains ESP when exception happened
467
468    # call handleKernelException(vector, errcode, EIP, ESP, EFLAGS, CR0, CR2, CR3, CR4)
469    movl    %cr4, %esi
470    pushl   %esi
471    movl    %cr3, %esi
472    pushl   %esi
473    movl    %cr2, %esi
474    pushl   %esi
475    movl    %cr0, %esi
476    pushl   %esi
477    pushl   %edx
478    pushl   %edi
479    pushl   %ebx
480    pushl   %eax
481    pushl   %ecx
482    call    handleKernelException
483    addl    $36, %esp
484    # Set EIP in the saved register context to the new IP returned from handleKernelException
485    movl    %eax, (4 * NextIP)(%esp)
486    jmp     kernel_int_return
487END_FUNC(kernel_exception)
488
489# Handle vmexit
490# ESP points to the end of an array that just holds the general purpose registers
491#ifdef CONFIG_VTX
492BEGIN_FUNC(handle_vmexit)
493    pushl   %ebp
494    pushl   %edi
495    pushl   %esi
496    pushl   %edx
497    pushl   %ecx
498    pushl   %ebx
499    pushl   %eax
500
501    # Reset segment selectors
502    RESET_SELECTORS(ecx)
503
504    # switch to kernel stack
505    SET_KERNEL_STACK_FROM(7 * 4)
506    # Handle the vmexit, we will not return
507    call    c_handle_vmexit
508END_FUNC(handle_vmexit)
509#endif
510
511# Handle Syscall (coming via sysenter)
512# Assume following register contents when called:
513#   EAX : syscall number
514#   ECX : user ESP
515#   EDX : user EIP (pointing to the sysenter instruction)
516#   ESP : points to tss.esp0 which points to the end of the thread's registers array
517
518BEGIN_FUNC(handle_syscall)
519#ifndef CONFIG_HARDWARE_DEBUG_API
520    movl    (%esp), %esp    # ESP := tss.esp0
521#endif
522
523    subl    $4, %esp        # skip SS
524    pushl   %ecx            # save ESP (passed in ECX)
525    pushfl                  # save EFLAGS
526    orl     $0x200, (%esp)  # set interrupt bit in saved EFLAGS
527    subl    $4, %esp        # skip CS
528    pushl   %edx            # NextIP := EDX
529    pushl   $-1             # save Error (-1 means we entered via syscall)
530    pushl   %edx            # save FaultIP (passed in EDX)
531    pushl   %ebp            # save EBP (reply register)
532    pushl   %edi            # save EDI (message register)
533    pushl   %esi            # save ESI (msgInfo register)
534    pushl   %edx            # save EDX (contains FaultIP)
535    pushl   %ecx            # save ECX (contains ESP)
536    pushl   %ebx            # save EBX (cap/badge register)
537    pushl   %eax            # save EAX (syscall number)
538    pushl   $0
539
540    # Reset segment selectors
541    RESET_SELECTORS(ecx)
542
543    # switch to kernel stack
544    SET_KERNEL_STACK
545
546    # Push all the arguments for c_handle_syscall
547#ifdef CONFIG_KERNEL_MCS
548    pushl   %ebp # reply
549#endif
550    pushl   %eax # syscall number
551    pushl   %esi # msgInfo
552    pushl   %ebx # cptr
553
554    # gtfo to C land, we will not return
555    call    c_handle_syscall
556
557END_FUNC(handle_syscall)
558