There is no need to save and load sse state on every interrupt. Instead we can use CR0.TS to make threads trigger an interrupt when they use sse instructions. This can be used to only save and load sse state when needed. Processor now keeps track of its current "sse thread" and the scheduler either enabled or disabled sse based on which thread it is starting up. When a thread dies, it checks if it was the current sse thread to avoid use after free bugs. When load balancing, processor has to save the thread's sse state before sending it to a new processor (if it was the current sse thread). This ensures thread's sse state will be correct when the new processor ends up loading it.
36 lines
502 B
ArmAsm
36 lines
502 B
ArmAsm
# uint64_t read_ip()
|
|
.global read_ip
|
|
read_ip:
|
|
popq %rax
|
|
jmp *%rax
|
|
|
|
# void start_kernel_thread()
|
|
.global start_kernel_thread
|
|
start_kernel_thread:
|
|
call get_thread_start_sp
|
|
movq %rax, %rsp
|
|
|
|
# STACK LAYOUT
|
|
# on_exit arg
|
|
# on_exit func
|
|
# entry arg
|
|
# entry func
|
|
|
|
movq 8(%rsp), %rdi
|
|
movq 0(%rsp), %rsi
|
|
sti
|
|
call *%rsi
|
|
|
|
movq 24(%rsp), %rdi
|
|
movq 16(%rsp), %rsi
|
|
call *%rsi
|
|
|
|
.global start_userspace_thread
|
|
start_userspace_thread:
|
|
call get_thread_start_sp
|
|
movq %rax, %rsp
|
|
|
|
swapgs
|
|
|
|
iretq
|