summaryrefslogtreecommitdiff
path: root/kernel/cpu/io.s
blob: 31e9df07ff2593bc0a2ea5ec2bab9d6a932c2f19 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
.intel_syntax noprefix
.global outsw
.global outb
.global outw
.global outl
.global inb
.global inw
.global inl
.global rep_outsw
.global rep_insw
.global flush_tss
.global load_idtr

# ebx, esi, edi, ebp, and esp;
outsw:
        push ebp
	mov ebp, esp
	push esi
	mov dx, [ebp + 4+4]
	mov esi, [ebp + 8+4]
	outsw
	pop esi
	mov esp, ebp
	pop ebp
	ret

outl:
	mov eax, [esp + 8]
	mov dx, [esp + 4]
	out dx, eax
	ret

outb:
	mov al, [esp + 8]
	mov dx, [esp + 4]
	out dx, al
	ret

outw:
	mov ax, [esp + 8]
	mov dx, [esp + 4]
	out dx, ax
	ret

inl:
	mov dx, [esp + 4]
	in  eax, dx
	ret

inw:
	mov dx, [esp + 4]
	in  ax, dx
	ret

inb:
	mov dx, [esp + 4]
	in  al, dx
	ret

rep_outsw:
        push ebp
	mov ebp, esp
	push edi
	mov ecx, [ebp + 4+4]      #ECX is counter for OUTSW
	mov edx, [ebp + 8+4]      #Data port, in and out
	mov edi, [ebp + 12+4]		#Memory area
	rep outsw               #in to [RDI]
	pop edi
	mov esp, ebp
	pop ebp
	ret

rep_insw:
        push ebp
	mov ebp, esp
	push edi
	mov ecx, [ebp + 4+4]      #ECX is counter for INSW
	mov edx, [ebp + 8+4]      #Data port, in and out
	mov edi, [ebp + 12+4]		#Memory area
	rep insw                #in to [RDI]
	pop edi
	mov esp, ebp
	pop ebp
	ret

flush_tss:
	mov ax, 40
	ltr ax
	ret

load_idtr:
	mov edx, [esp + 4]
	lidt [edx]
	ret

test_user_function:
	mov eax, 0x00
	int 0x80
	mov ecx, 0x03
	mov ebx, 0x04
	mov eax, 0x02
	int 0x80
	mov ebx, eax
	mov eax, 0x01
	int 0x80
loop:
	jmp loop
	ret

.global spin_lock
.global spin_unlock
.extern locked

spin_lock:
	mov eax, 1
	xchg eax, ebx
	test eax, eax     
	jnz spin_lock
	ret

spin_unlock:
	xor eax, eax
	xchg eax, ebx
	ret


.global jump_usermode
jump_usermode:
	mov ax, (4 * 8) | 3 # user data segment with RPL 3
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax # sysexit sets SS
 
	# setup wrmsr inputs
	xor edx, edx # not necessary; set to 0
	mov eax, 0x100008 # SS=0x10+0x10=0x20, CS=0x8+0x10=0x18
	mov ecx, 0x174 # MSR specifier: IA32_SYSENTER_CS
	wrmsr # set sysexit segments
 
	# setup sysexit inputs
	mov edx, [esp + 4] # to be loaded into EIP
	mov ecx, [esp + 8] # to be loaded into ESP
	mov esp, ecx
	mov ebp, ecx
	sti
	sysexit