]> pd.if.org Git - zos/blob - taskx64.s
add a readme with a public domain note
[zos] / taskx64.s
1 extern allstop
2 extern printk
3 extern print_decode_p
4 extern test_address
5
6 global getrflags:function
7 getrflags:
8         pushf
9         mov rax, [rsp]
10         popf
11         ret
12
13 global switch_task:function
14
15 ; this needs to be in sync with the definition in process.h
16 struc reg
17         .kerrno resq 1 ;
18         .rax resq 1 ;
19         .rbx resq 1 ;
20         .rcx resq 1 ;
21         .rdx resq 1 ;
22         .rdi resq 1 ;
23         .rsi resq 1 ;
24         .rsp resq 1 ;
25         .rbp resq 1 ;
26         .r8 resq 1 ;
27         .r9 resq 1 ;
28         .r10 resq 1 ;
29         .r11 resq 1 ;
30         .r12 resq 1 ;
31         .r13 resq 1 ;
32         .r14 resq 1 ;
33         .r15 resq 1 ;
34         .rip resq 1 ;
35         .rflags resq 1 ;
36         .cr3 resq 1 ;
37         .kernel_stack resq 1 ;
38         .cs resq 1 ;
39         .ss resq 1 ;
40 endstruc
41
42 %macro  multipush 1-*
43
44   %rep  %0
45         push    %1
46   %rotate 1
47   %endrep
48
49 %endmacro
50
51 ; first arg rdi is old register pointer, second arg is new register pointer
52 switch_task:
53         ; save old registers
54         mov [rdi + reg.rax], rax
55         mov [rdi + reg.rbx], rbx
56         mov [rdi + reg.rcx], rcx
57         mov [rdi + reg.rdx], rdx
58         mov [rdi + reg.rdi], rdi ; a pointer to the current task
59         mov [rdi + reg.rsi], rsi ; though rsi is just a pointer to the new task...
60         mov [rdi + reg.rbp], rbp
61         mov [rdi + reg.r8], r8
62         mov [rdi + reg.r9], r9
63         mov [rdi + reg.r10], r10
64         mov [rdi + reg.r11], r11
65         mov [rdi + reg.r12], r12
66         mov [rdi + reg.r13], r13
67         mov [rdi + reg.r14], r14
68         mov [rdi + reg.r15], r15
69         ; save rip for return from stack
70         ; mov?  we're going to switch the stack anyway
71         pop rax
72         mov [rdi + reg.rip], rax
73
74 ;       push rdi
75 ;       push rsi
76 ;       mov rdi, qword printrrip
77 ;       mov rsi, [rsp]
78 ;       call printk
79 ;       pop rsi
80 ;       pop rdi
81
82         mov [rdi + reg.rsp], rsp
83
84         ; save rflags
85         pushf
86         pop rax
87         mov [rdi + reg.rflags], rax
88         ; and the address space
89         ; TODO skip, shouldn't change
90         mov rax, cr3
91         mov [rdi + reg.cr3], rax
92
93 .loadregisters
94         ; Ok.  now load up the new registers
95         ; we're going to use rax and rbx, and rsi needs
96         ; to be last
97         mov rcx, [rsi + reg.rcx]
98         mov rdx, [rsi + reg.rdx]
99         mov rdi, [rsi + reg.rdi]
100         mov rbp, [rsi + reg.rbp]
101         mov r8,  [rsi + reg.r8]
102         mov r9,  [rsi + reg.r9]
103         mov r10, [rsi + reg.r10]
104         mov r11, [rsi + reg.r11]
105         mov r12, [rsi + reg.r12]
106         mov r13, [rsi + reg.r13]
107         mov r14, [rsi + reg.r14]
108         mov r15, [rsi + reg.r15]
109
110 ;       push rdi
111 ;       push rsi
112 ;       mov rdi, qword printsp
113 ;       mov rsi, [rsi + reg.rsp]
114 ;       call printk
115 ;       pop rsi
116 ;       pop rdi
117
118
119         ; and the address space
120         ; rsi should be pointing into the kernel
121         ; memory, so we can still load from that
122         ; address
123         mov rax, cr3
124         mov rbx, [rsi + reg.cr3]
125         mov dr1, rax
126         mov dr2, rbx
127         cmp rbx, rax
128         je .skipspaceload
129
130         mov cr3, rbx
131         mov rbx, cr3
132         mov dr3, rbx
133         ; switch to new stack, has to be after the address space switch, otherwise the
134         ; stack isn't mapped
135
136 .skipspaceload:
137
138         mov rsp, [rsi + reg.rsp]
139
140         ; load rflags
141         mov rax, [rsi + reg.rflags]
142         ;call printrax
143         push rax
144         popf
145
146         ; push rip for return from stack
147         ; must be done after we switch address space
148         mov rax, [rsi + reg.rip]
149         push rax
150
151 ;       push rdi
152 ;       push rsi
153 ;       mov rdi, qword printrip
154 ;       ;mov rsi, [rsi + reg.rip]
155 ;       mov rsi, [rsp]
156 ;       call printk
157 ;       pop rsi
158 ;       pop rdi
159
160         ; restore registers we used for the switch
161         mov rbx, [rsi + reg.rbx]
162         mov rax, [rsi + reg.rax]
163         mov rsi, [rsi + reg.rsi] ; have to do this one last
164
165         ret
166
167 global usermodetrampoline:function
168
169 usermodetrampoline:
170         ; sysret wants return rip in rcx
171         ; rflags in r11
172
173         ; user mode function in rdi (i.e. first argument)
174         push rdi
175
176         mov rax, rdi
177         call printrax
178         mov ecx, 0xc0000082
179         rdmsr
180         shl rdx, 32
181         or rdx, rax
182         mov rax, rdx
183         call printrax
184         
185 ; TODO clear out all the other registers to not leak anything
186 ; to userspace
187
188         pop rcx
189         mov r11, 0x202 ; make sure interrupts will be enabled
190         mov dr0, rdi
191 thesysret:
192         db 0x48 ; need rex prefix for 64 bit mode returns
193         sysret
194
195 section .data
196 printcr3: db 'cr3 = %llx', 0xA, 0
197 printsp: db 'setting rsp %llx', 0xA, 0
198 printrip: db 'returning to %llx', 0xA, 0
199 printrrip: db 'saving return to %llx', 0xA, 0
200
201 printcr3s: db 'old cr3 = %llx, new cr3 = %llx', 0xA, 0
202
203 section .text
204 dumpcr3:
205         push rdi
206         push rsi
207         push rdx
208         push rbx
209         push rax
210         mov rdi, qword printcr3s
211         mov rsi, rax
212         mov rdx, rbx
213         call printk
214         pop rax
215         pop rbx
216         pop rdx
217         pop rsi
218         pop rdi
219         ret
220
221 printraxs:
222         push rdi
223         push rsi
224         push rax
225         mov rdi, qword raxprintf
226         mov rsi, rax
227         call printk
228         call allstop
229         pop rax
230         pop rsi
231         pop rdi
232         ret
233 printrax:
234         push rdi
235         push rsi
236         push rax
237         mov rdi, qword raxprintf
238         mov rsi, rax
239         call printk
240         pop rax
241         pop rsi
242         pop rdi
243         ret
244
245 global printistack:function
246 printistack:
247         push rdi
248         push rsi
249         mov rdi, qword ssprintf
250         mov rsi, [rbx + 32]
251         call printk
252         mov rdi, qword rspprintf
253         mov rsi, [rbx + 24]
254         call printk
255         mov rdi, qword rfprintf
256         mov rsi, [rbx + 16]
257         call printk
258         mov rdi, qword csprintf
259         mov rsi, [rbx + 8]
260         call printk
261         mov rdi, qword ripprintf
262         mov rsi, [rbx + 0]
263         call printk
264         pop rsi
265         pop rdi
266         ret
267
268 rfprintf:  db 'rflags : %llx', 10, 0
269 csprintf:  db 'cs     : %hx', 10, 0
270 ripprintf: db 'rip    : %llx', 10, 0
271 raxprintf: db 'rax    : %llx', 10, 0
272 rspprintf: db 'rsp    : %llx', 10, 0
273 ssprintf:  db 'ss     : %hx', 10, 0
274 csvprintf: db 'gdt    : %016llx', 10, 0