]> wirehaze git hosting - ppos.git/blob - ppos/kernel/ctx.s

wirehaze git hosting

tasks implementation (ongoing)
[ppos.git] / ppos / kernel / ctx.s
1 # PingPongOS - PingPong Operating System
2 # Prof. Carlos A. Maziero, DINF UFPR
3 # Versão 2.0 -- Junho de 2025
4
5 # ATENÇÃO: ESTE ARQUIVO NÃO DEVE SER ALTERADO;
6 # ALTERAÇÕES SERÃO DESCARTADAS NA CORREÇÃO.
7
8 # Rotinas de manipulação de contextos no userspace, detalhes em ctx.h.
9 # Escrito em assembly com sintaxe AT&T (cmd source, dest)
10
11 #-----------------------------------------------------------------------
12
13 # register offsets in the ctx_t struct (defined in ctx.h)
14 .equ OFF_RIP, 8*0 # registers
15 .equ OFF_RSP, 8*1
16 .equ OFF_RBP, 8*2
17 .equ OFF_RDI, 8*3
18 .equ OFF_RSI, 8*4
19 .equ OFF_RAX, 8*5
20 .equ OFF_RBX, 8*6
21 .equ OFF_RCX, 8*7
22 .equ OFF_RDX, 8*8
23 .equ OFF_R8, 8*9
24 .equ OFF_R9, 8*10
25 .equ OFF_R10, 8*11
26 .equ OFF_R11, 8*12
27 .equ OFF_R12, 8*13
28 .equ OFF_R13, 8*14
29 .equ OFF_R14, 8*15
30 .equ OFF_R15, 8*16
31 .equ OFF_SSA, 8*17 # stack start address
32 .equ OFF_SSZ, 8*18 # stack size in bytes
33
34 #-----------------------------------------------------------------------
35
36 # saves the current context in ctx1 and transfers control to ctx2
37 .type ctx_swap, @function
38 .global ctx_swap
39
40 ctx_swap:
41 # Arguments:
42 # rdi: *ctx1
43 # rsi: *ctx2
44
45 # if ctx1 == ctx2, goto error
46 cmp %rdi, %rsi
47 jz ctx_swap_error
48
49 # if ctx1 == NULL, do not save current context
50 cmp $0, %rdi
51 jz ctx_swap_load_ctx2
52
53 # save CPU registers in ctx1 struct
54 mov %r8, OFF_R8(%rdi) # ctx->r8 = %r8
55 mov %r9, OFF_R9(%rdi) # ...
56 mov %r10, OFF_R10(%rdi)
57 mov %r11, OFF_R11(%rdi)
58 mov %r12, OFF_R12(%rdi)
59 mov %r13, OFF_R13(%rdi)
60 mov %r14, OFF_R14(%rdi)
61 mov %r15, OFF_R15(%rdi)
62 mov %rax, OFF_RAX(%rdi)
63 mov %rbx, OFF_RBX(%rdi)
64 mov %rcx, OFF_RCX(%rdi)
65 mov %rdx, OFF_RDX(%rdi)
66 mov %rdi, OFF_RDI(%rdi)
67 mov %rsi, OFF_RSI(%rdi)
68 mov %rbp, OFF_RBP(%rdi)
69
70 # Current stack state:
71 # : :
72 # : :
73 # +---------------------+
74 # | caller stack bottom | <- stack pointer before calling ctx_swap
75 # +---------------------+
76 # | ret addr (8 bytes) | <- stack pointer now (%rsp)
77 # +---------------------+
78
79 # save the return address in ctx1->rip
80 mov (%rsp), %rcx # %rcx = *(%rsp)
81 mov %rcx, OFF_RIP(%rdi) # *(%rdi + OFF_RIP) = %rcx
82
83 # save the previous stack pointer in ctx1->rsp
84 lea 8(%rsp), %rcx # %rcx = *(%rsp + 8)
85 mov %rcx, OFF_RSP(%rdi) # *(%rdi + OFF_RSP) = %rcx
86
87 ctx_swap_load_ctx2:
88 # if ctx2 == NULL, do not load ctx2 into the CPU
89 cmp $0, %rsi
90 jz ctx_swap_noerror
91
92 # load CPU registers from ctx2 struct, except %rsi because
93 # its current value is being used
94 mov OFF_R8(%rsi), %r8 # %r8 = *(%rsi + OFF_R8)
95 mov OFF_R9(%rsi), %r9 # ...
96 mov OFF_R10(%rsi), %r10
97 mov OFF_R11(%rsi), %r11
98 mov OFF_R12(%rsi), %r12
99 mov OFF_R13(%rsi), %r13
100 mov OFF_R14(%rsi), %r14
101 mov OFF_R15(%rsi), %r15
102 mov OFF_RAX(%rsi), %rax
103 mov OFF_RBX(%rsi), %rbx
104 mov OFF_RCX(%rsi), %rcx
105 mov OFF_RDX(%rsi), %rdx
106 mov OFF_RDI(%rsi), %rdi
107 # mov OFF_RSI(%rsi), %rsi # do this later
108 mov OFF_RBP(%rsi), %rbp
109 mov OFF_RSP(%rsi), %rsp
110
111 # load the saved RIP and push it in the stack;
112 # it will be the return address when calling ret below
113 push OFF_RIP(%rsi)
114
115 # now we can load %rsi with value stored in ctx2->rsi
116 mov OFF_RSI(%rsi), %rsi
117
118 ctx_swap_noerror:
119 # no errors, return 0
120 xor %eax, %eax
121 ret
122
123 ctx_swap_error:
124 # error, return -1
125 movl $-1, %eax
126 ret
127
128 #-----------------------------------------------------------------------
129
130 # set entry point, arg, and stack for the context given as parameter
131 .type ctx_create, @function
132 .global ctx_create
133
134 ctx_create:
135 # Arguments:
136 # %rdi: *ctx
137 # %rsi: *entry
138 # %rdx: *arg
139 # %rcx: *stack
140 # %r8 : size
141
142 # if ctx == NULL, goto error
143 cmp $0, %rdi
144 jz ctx_create_error
145
146 # if entry == NULL, goto error
147 cmp $0, %rsi
148 jz ctx_create_error
149
150 # if stack == NULL, goto error
151 cmp $0, %rcx
152 jz ctx_create_error
153
154 # if stack is not 16-byte aligned, goto error
155 # (last 4 bits of %rcx should be zero)
156 test $0x0F, %rcx # 0x0F = 00001111
157 jnz ctx_create_error
158
159 # if stack size < 4K, goto error
160 cmp $0x1000, %r8 # 0x1000 = 4096
161 jl ctx_create_error
162
163 # save current CPU registers in ctx struct
164 mov %r8, OFF_R8(%rdi) # ctx->r8 = %r8
165 mov %r9, OFF_R9(%rdi) # ...
166 mov %r10, OFF_R10(%rdi)
167 mov %r11, OFF_R11(%rdi)
168 mov %r12, OFF_R12(%rdi)
169 mov %r13, OFF_R13(%rdi)
170 mov %r14, OFF_R14(%rdi)
171 mov %r15, OFF_R15(%rdi)
172 mov %rax, OFF_RAX(%rdi)
173 mov %rbx, OFF_RBX(%rdi)
174 mov %rcx, OFF_RCX(%rdi)
175 mov %rdx, OFF_RDX(%rdi)
176 mov %rdi, OFF_RDI(%rdi)
177 mov %rsi, OFF_RSI(%rdi)
178 mov %rbp, OFF_RBP(%rdi)
179
180 # save context's stack address and size
181 mov %rcx, OFF_SSA(%rdi) # ctx->stack = stack
182 mov %r8, OFF_SSZ(%rdi) # ctx->size = size
183
184 # set context's stack base and pointer; both should point to
185 # the top of the stack area provided and should be 16-byte
186 # aligned (stack + size - 16)
187 add %r8, %rcx # stack += size
188 sub $0x10, %rcx # stack -= 16
189 mov %rcx, OFF_RBP(%rdi) # ctx->rbp = stack
190 mov %rcx, OFF_RSP(%rdi) # ctx->rsp = stack
191
192 # ctx->rsp should be decremented by 8 to keep it 16-byte aligned
193 # when the ctx_swap function returns, because the ret instruction
194 # pops an 8-byte return address from the stack
195 subq $0x8, OFF_RSP(%rdi) # ctx->rsp -= 8
196
197 # set context's entry point (function)
198 mov %rsi, OFF_RIP(%rdi) # ctx->rip = entry
199
200 # set entry point function argument
201 mov %rdx, OFF_RDI(%rdi) # ctx->rdi = arg
202
203 # no errors, return 0
204 xor %eax, %eax
205 ret
206
207 ctx_create_error:
208 # errors, return -1
209 movl $-1, %eax
210 ret
211
212 #-----------------------------------------------------------------------s