kern

view src/intr-asm.S @ 55:88a6c4e192f9

Fixed most important task switching bugs. Now it seems that I can switch in and out of user space reliably.
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 15 Aug 2011 04:03:39 +0300
parents 4eaecb14fe31
children
line source
1 #define ASM
2 #include "segm.h"
4 .data
5 .align 4
6 .short 0
7 /* memory reserved for set_idt */
8 lim:.short 0
9 addr:.long 0
11 .text
12 /* set_idt(uint32_t addr, uint16_t limit)
13 * loads the IDTR with the new address and limit for the IDT */
14 .globl set_idt
15 set_idt:
16 movl 4(%esp), %eax
17 movl %eax, (addr)
18 movw 8(%esp), %ax
19 movw %ax, (lim)
20 lidt (lim)
21 ret
23 /* get_intr_state()
24 * returns 1 if interrutps are enabled, 0 if disabled */
25 .globl get_intr_state
26 get_intr_state:
27 pushf
28 popl %eax
29 shr $9, %eax /* bit 9 of eflags is IF */
30 andl $1, %eax
31 ret
33 /* set_intr_state(int state)
34 * enables interrupts if the argument is non-zero, disables them otherwise */
35 .globl set_intr_state
36 set_intr_state:
37 cmpl $0, 4(%esp)
38 jz 0f
39 sti
40 ret
41 0: cli
42 ret
45 /* interrupt entry with error code macro
46 * this macro generates an interrupt entry point for the
47 * exceptions which include error codes in the stack frame
48 */
49 .macro ientry_err n name
50 .globl intr_entry_\name
51 intr_entry_\name:
52 pushl $\n
53 jmp intr_entry_common
54 .endm
56 /* interrupt entry without error code macro
57 * this macro generates an interrupt entry point for the interrupts
58 * and exceptions which do not include error codes in the stack frame
59 * it pushes a dummy error code (0), to make the stack frame identical
60 */
61 .macro ientry_noerr n name
62 .globl intr_entry_\name
63 intr_entry_\name:
64 pushl $0
65 pushl $\n
66 jmp intr_entry_common
67 .endm
69 /* common code used by all entry points. calls dispatch_intr()
70 * defined in intr.c
71 */
72 .extern dispatch_intr
73 intr_entry_common:
74 /* save the current data segment selectors */
75 pushl %gs
76 pushl %fs
77 pushl %es
78 pushl %ds
79 /* save general purpose registers */
80 pusha
81 /* if we entered from userspace ss and cs is set correctly, but
82 * we must make sure all the other selectors are set to the
83 * kernel data segment */
84 mov %ss, %eax
85 mov %eax, %ds
86 mov %eax, %es
87 mov %eax, %fs
88 mov %eax, %gs
89 call dispatch_intr
90 intr_ret_local:
91 /* restore general purpose registers */
92 popa
93 /* restore data segment selectors */
94 popl %ds
95 popl %es
96 popl %fs
97 popl %gs
98 /* remove error code and intr num from stack */
99 add $8, %esp
100 iret
102 /* intr_ret is called by context_switch to return from the kernel
103 * to userspace. The argument is a properly formed intr_frame
104 * structure with the saved context of the new task.
105 *
106 * First thing to do is remove the return address pointing back
107 * to context_switch, which then leaves us with a proper interrupt
108 * stack frame, so we can jump right in the middle of the regular
109 * interrupt return code above.
110 */
111 .globl intr_ret
112 intr_ret:
113 add $4, %esp
114 jmp intr_ret_local
116 /* by including interrupts.h with ASM defined, the macros above
117 * are expanded to generate all required interrupt entry points
118 */
119 #include <interrupts.h>