AquilaOS documentation
How it works, and its code
Loading...
Searching...
No Matches
fpsimd.c
Go to the documentation of this file.
1
16
17#include <core/system.h>
18#include <core/arch.h>
19#include <core/string.h>
20#include <cpu/cpu.h>
21#include <sys/proc.h>
22#include <sys/sched.h>
23#include <sys/signal.h>
24
25MALLOC_DEFINE(M_FPSIMD, "fpsimd", "a thread's FP/SIMD registers");
26
27/* CPACR_EL1.FPEN: user mode's use traps (0b01), or nothing does (0b11). */
28#define CPACR_FPEN_EL0_TRAP (1UL << 20) /* 0b01 */
29#define CPACR_FPEN_NONE (3UL << 20) /* 0b11 */
30
31/* Saves the registers to `state`, or loads them from it (fpsimd_regs.S). */
32
33void aarch64_fpsimd_save(void *state);
34void aarch64_fpsimd_load(const void *state);
35
36/* The thread whose values this CPU's registers hold. */
37#define fp_thread (curcpu()->arch.fp_thread)
38
40static void fpen(uint64_t v)
41{
42 write_sysreg(cpacr_el1, v);
43 isb();
44}
45
56
65{
66 struct aarch64_thread *arch = thread->arch;
67
68 if (arch->fpsimd && fp_thread == thread)
70
71 return arch->fpsimd;
72}
73
81{
82 struct thread *thread = curthread;
83 struct aarch64_thread *arch = thread->arch;
84
85 if (!arch->fpsimd && !(arch->fpsimd = kmalloc(FPSIMD_STATE_SIZE, &M_FPSIMD, M_ZERO)))
86 return -ENOMEM;
87
88 if (fp_thread != thread) {
89 if (fp_thread && fp_thread->arch)
90 aarch64_fpsimd_save(((struct aarch64_thread *) fp_thread->arch)->fpsimd);
91
94 }
95
97 return 0;
98}
99
107{
108 struct aarch64_thread *arch = thread->arch;
109
110 if (fp_thread == thread) {
111 fp_thread = NULL;
113 }
114
115 if (arch) {
116 kfree(arch->fpsimd);
117 arch->fpsimd = NULL;
118 }
119}
120
129int aarch64_fpsimd_fork(struct thread *parent, struct aarch64_thread *child)
130{
131 void *state = aarch64_fpsimd_current(parent);
132
133 if (!state)
134 return 0;
135
136 if (!(child->fpsimd = kmalloc(FPSIMD_STATE_SIZE, &M_FPSIMD, 0)))
137 return -ENOMEM;
138
139 memcpy(child->fpsimd, state, FPSIMD_STATE_SIZE);
140 return 0;
141}
142
151void aarch64_fpsimd_restore(struct thread *thread, const void *state)
152{
153 struct aarch64_thread *arch = thread->arch;
154
155 if (fp_thread == thread) {
156 fp_thread = NULL;
158 }
159
160 if (state && arch->fpsimd)
161 memcpy(arch->fpsimd, state, FPSIMD_STATE_SIZE);
162 else if (arch->fpsimd)
164}
#define FPSIMD_STATE_SIZE
Definition arch.h:44
#define isb()
Definition cpu.h:45
#define write_sysreg(r, v)
Definition cpu.h:39
#define CPACR_FPEN_NONE
Definition fpsimd.c:29
#define fp_thread
Definition fpsimd.c:37
void * aarch64_fpsimd_current(struct thread *thread)
Returns a thread's FP/SIMD state as it is now, saving it from the registers first if they hold it.
Definition fpsimd.c:64
void aarch64_fpsimd_drop(struct thread *thread)
Throws away a thread's FP/SIMD state, when it goes or execs a new program, and the registers' values ...
Definition fpsimd.c:106
void aarch64_fpsimd_save(void *state)
void aarch64_fpsimd_switch(struct thread *thread)
Gets the registers ready for a thread that is about to run: its use of them traps,...
Definition fpsimd.c:52
static void fpen(uint64_t v)
Sets CPACR_EL1.FPEN: whether user mode's use traps.
Definition fpsimd.c:40
int aarch64_fpsimd_fork(struct thread *parent, struct aarch64_thread *child)
Gives a child of fork() a copy of its parent's FP/SIMD state, if the parent has one.
Definition fpsimd.c:129
int aarch64_fpsimd_trap(void)
Handles the trap of user mode's use of the registers: they get the running thread's values,...
Definition fpsimd.c:80
void aarch64_fpsimd_restore(struct thread *thread, const void *state)
Gives a thread back the FP/SIMD state that a signal frame kept, for sigreturn().
Definition fpsimd.c:151
void aarch64_fpsimd_load(const void *state)
#define CPACR_FPEN_EL0_TRAP
Definition fpsimd.c:28
#define MALLOC_DEFINE(type, _name, _desc)
Definition kvmem.h:30
void * kmalloc(size_t size, struct malloc_type *type, int flags)
Allocates memory for one of the kernel's structures.
Definition kvmem.c:123
#define M_ZERO
Definition kvmem.h:26
void kfree(void *)
Frees an object that kmalloc() gave.
Definition kvmem.c:146
void * memset(void *dst, int c, size_t n)
Sets n bytes to c.
Definition libc.c:23
void * memcpy(void *dst, const void *src, size_t n)
Copies n bytes; dst and src must not overlap.
Definition libc.c:11
#define curthread
Definition sched.h:12
#define NULL
Definition stddef.h:27
unsigned long long int uint64_t
Definition stddef.h:23
A thread's aarch64 state (thread->arch).
Definition arch.h:25
void * fpsimd
Definition arch.h:40
A thread.
Definition thread.h:23
void * arch
the architecture's own data: its registers, its kernel stack
Definition thread.h:84