1 # PingPongOS - PingPong Operating System
2 # Prof. Carlos A. Maziero, DINF UFPR
3 # Versão 2.0 -- Junho de 2025
5 # ATENÇÃO: ESTE ARQUIVO NÃO DEVE SER ALTERADO;
6 # ALTERAÇÕES SERÃO DESCARTADAS NA CORREÇÃO.
8 # Rotinas de manipulação de contextos no userspace, detalhes em ctx.h.
9 # Escrito em assembly com sintaxe AT&T (cmd source, dest)
11 #-----------------------------------------------------------------------
13 # register offsets in the ctx_t struct (defined in ctx.h)
14 .equ OFF_RIP, 8*0 # registers
31 .equ OFF_SSA, 8*17 # stack start address
32 .equ OFF_SSZ, 8*18 # stack size in bytes
34 #-----------------------------------------------------------------------
36 # saves the current context in ctx1 and transfers control to ctx2
37 .type ctx_swap, @function
45 # if ctx1 == ctx2, goto error
49 # if ctx1 == NULL, do not save current context
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)
70 # Current stack state:
73 # +---------------------+
74 # | caller stack bottom | <- stack pointer before calling ctx_swap
75 # +---------------------+
76 # | ret addr (8 bytes) | <- stack pointer now (%rsp)
77 # +---------------------+
79 # save the return address in ctx1->rip
80 mov (%rsp), %rcx # %rcx = *(%rsp)
81 mov %rcx, OFF_RIP(%rdi) # *(%rdi + OFF_RIP) = %rcx
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
88 # if ctx2 == NULL, do not load ctx2 into the CPU
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
111 # load the saved RIP and push it in the stack;
112 # it will be the return address when calling ret below
115 # now we can load %rsi with value stored in ctx2->rsi
116 mov OFF_RSI(%rsi), %rsi
119 # no errors, return 0
128 #-----------------------------------------------------------------------
130 # set entry point, arg, and stack for the context given as parameter
131 .type ctx_create, @function
142 # if ctx == NULL, goto error
146 # if entry == NULL, goto error
150 # if stack == NULL, goto error
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
159 # if stack size < 4K, goto error
160 cmp $0x1000, %r8 # 0x1000 = 4096
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)
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
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
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
197 # set context's entry point (function)
198 mov %rsi, OFF_RIP(%rdi) # ctx->rip = entry
200 # set entry point function argument
201 mov %rdx, OFF_RDI(%rdi) # ctx->rdi = arg
203 # no errors, return 0
212 #-----------------------------------------------------------------------s